在运用模板方法模式来解决我们的需求而进行设计时,往往忽略了一些非常重要的细节。保证架构逻辑的正常执行,不被子类破坏(模板方法加final关键字);怎么让子类扩展模板方法等。抽象模板中的基本方法尽量设计为protected类型的,符合迪米特法则.
迪米特法则(LoD):又称最少知识原则(LKP),就是说一个对象应当对其他对象尽可能少的了解。如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用.如果其中一个类需要调用另一个类的方法的话,可以通过第三者转发这个调用.
1.模板方法设计模式的意图
通常我们会遇到这样的一个问题:我们知道一个算法所需的关键步聚,并确定了这些步聚的执行顺序。但是某些步聚的具体实现是未知的,或者是某些步聚的实现与具体的环境相关。模板方法模式把我们不知道具体实现的步聚封装成抽象方法,提供一些按正确顺序调用它们的具体方法(这些具体方法统称为模板方法),这样构成一个抽象基类。子类通过继承这个抽象基类去实现各个步聚的抽象方法,而工作流程却由父类来控制。
2.模板方法模式定义及结构
考虑一个简单的订单处理需求:一个客户可以在个订货单中订购多个货物(也称为订货单项目),货物的销售价是根据货物的进货价进行计算的。有些货物可以打折的,有些是不可以打折的。每一个客户都有一个信用额度,每张订单的总价不能超出该客户的信用额度。
根据上面的业务,我们可以知道处理一个订单需要的步聚:
1.遍历订货单的订货单项目列表,累加所有货物的总价格(根据订货单项目计算出销售价)
2.根据客户号获得客户的信用额度
3.把客户号,订单的总价格,及订单项目列表写入到数据库
但是我们并不能确定怎么计算出货物的销售价,怎样根据客户号获得客户的信用额度及把订单信息写入数据库这些方法的具体实现。
所以用一个抽象类AbstractOrder确定订单处理的逻辑,把不能确定的方法定义为抽象方法,由子类去完成具体的实现。
抽象模板类
public abstract class AbstractOrder {
//模板方法
public Order placeOrder(int customerId , List orderItemList){
int total = 0;
for(int i = 0; i < orderItemList.size();i++){
OrderItem orderItem = (OrderItem)orderItemList.get(i);
Total += getOrderItemPrice(orderItem) * orderItem.getQuantity();
}
if(total > getSpendingLimit(customerId)){
throw new BusinessException(“超出信用额度” + getSpendingLimit(customerId));
}
int orderId = saveOrder(customerId, total, orderItemList);
return new OrderImpl(orderId,total);
}
//基本方法
public abstract int getOrderItemPrice(OrderItem orderItem);
//基本方法
public abstract int getSpendingLimit(int customerId);
//基本方法
public abstract int saveOrder(int customerId, int total, List orderItemList);
}
具体类
Public class ConcreteOrder extends AbstractOrder{
public int getOrderItemPrice(OrderItem orderItem){
//计算货物的售价
……
}
public int getSpendingLimit(int customerId){
//读取客户的信用额度
…..
}
public int saveOrder(int customerId, int total, List orderItemList){
//写入数据库
……
}
}
3.模板方法模式与控制反转
“不要给我们打电话,我们会给你打电话”这是著名的好莱坞原则。模板方法模式充分的体现了“好莱坞”原则。由父类完全控制着子类的逻辑,这就是控制反转。子类可以实现父类的可变部分,但不能改变业务逻辑。
4.模板方法模式与开闭原则
开闭原则是指一个软件实体应该对扩展开放,对修改关闭。也就是说软件实体必须是在不被修改的情况下被扩展。模板方法模式意图是由抽象父类控制顶级逻辑,并把基本操作的实现推迟到子类去实现,这是通过继承的手段来达到对象的复用,同时也遵守了开闭原则。
5.模板方法模式与对象的封装性
面向对象的三大特点:继承,封装,多态
对象有内部状态和外部的行为。封装是为了信息隐藏,通过封装来维护对象内部数据的完整性。使得外部对象不能够直接访问一个对象的内部状态,而必须通过恰当的方法才能访问。
在java语言中,采用给对象属性和方法赋予指定的修改符(public ,protected,private)来达到封装的目的,使得数据不被外部对象恶意的访问及方法不被错误调用从而破坏对象的封装性。
6.模板方法模式与策略模式
模板方法模式与策略模式的作用相常类似。有时可以用策略模式替代模板方法模式。模板方法模式通过继承来实现代码复用,策略模式使用委托,委托比继承具有更大的灵活性。继承经常被错误的使用。
策略模式把不确定的行为集中到一个接口(OrderHelper)中,并在主类(Order)委托(set 方式注入)这个接口。思考上面的订单处理例子,改为策略模式后。
1).把不确定的行为抽取为一个接口。
Public interface OrderHelper{
public int getOrderItemPrice(OrderItem orderItem);
public int getSpendingLimit(int customerId);
public int saveOrder(int customerId, int total, List orderItemList);
}
2). 主类调用这个接口的相应方法来实现具体的逻辑。
public class Order {
//委托的接口
private OrderHelper orderHelpr;
public void setOrderHelper(OrderHelper orderHelper){
this.orderHelper = orderHelper;
}
//具体逻辑
public Order placeOrder(int customerId , List orderItemList){
int total = 0;
for(int i = 0; i < orderItemList.size();i++){
OrderItem orderItem = (OrderItem)orderItemList.get(i);
Total += orderHelpr .getOrderItemPrice(orderItem) * orderItem.getQuantity();
}
if(total > orderHelpr .getSpendingLimit(customerId)){
throw new BusinessException(“超出信用额度” + orderHelpr .getSpendingLimit(customerId));
}
int orderId = orderHelpr .saveOrder(customerId, total, orderItemList);
return new OrderImpl(orderId,total);
}
}
这样Order类不再是一个抽象类,而是一个具体类。Order类委托OrderHelpher接口来完成placeOrder方法所需的基本操作。像在这种情况下使用策略模式更具有优势,策略模式不需要继承来实现。而是通过一个委托对象来实现。OrderHelper接口无需要去继续任何指定的类。而相对来说,采用策略来实现会更复杂一些。由此可见,模板方法模式主要应用于框架设计中,以确保基类控制处理流程的逻辑顺序(如框架的初始化)。而在下面一些情况中,优级先考虑使用策略模式:当需要变化的操作非常多时,采用策略模式把这些操作抽取到一个接口。 当那些基本操作的实现需要与其它类相关时,应该使用策略模式。通过委托接口把行为与实现完全分离出来(比如数据存取)。 比如订单处理的saveOrder方法,是写入数据库的。它的实现与你采用何种持久化模式相关。 当某些基本操作的实现可能需要在运行时改变时,可以通过在运行时改变委托对象来实现,而继承则不能。所以采用策略模式。
- 大小: 72.1 KB
分享到:
相关推荐
8. 模板方法模式(Template Method Pattern):在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。 9. 状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为。 10. 观察者模式...
2. **模板方法模式(Template Method)**:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。 3. **观察者模式(Observer)**:定义对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的...
例如,单例模式确保一个类只有一个实例,而工厂方法模式则提供了一种创建对象而不暴露其创建过程的方式。 3. **结构型模式** 结构型模式关注如何将类或对象组合成更大的结构,比如适配器(Adapter)、桥接(Bridge...
3. **行为型模式**(Behavioral Patterns):关注对象之间的责任分配和通信,包括策略模式(Strategy)、模板方法模式(Template Method)、迭代器模式(Iterator)、观察者模式(Observer)、访问者模式(Visitor)...
12. 模板方法模式(Template Method):定义一个操作中的算法骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 13. 观察者模式(Observer):定义对象间的一种...
- **行为型模式**:如策略(Strategy)、模板方法(Template Method)、观察者(Observer)、迭代器(Iterator)、访问者(Visitor)、命令(Command)、责任链(Chain of Responsibility)、备忘录(Memento)、...
10. 模板方法模式(Template Method):定义一个操作中的算法骨架,而将一些步骤延迟到子类中。 11. 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作。 设计模式的学习不仅帮助我们编写更可维护...
责任链(Chain of Responsibility)、命令(Command)、解释器(Interpreter)、迭代器(Iterator)、中介者(Mediator)、备忘录(Memento)、观察者(Observable/Observer)、状态(State)、策略(Strategy)、模板方法(Template ...
### 23种设计模式学习笔记 #### 一、软件设计模式的概念与意义 **概念:** 软件设计模式(Software Design Pattern),又称设计模式,是一套被广泛采用、经过整理和分类的代码设计经验总结。它针对软件设计过程中...
模板方法模式是一种行为设计模式,定义了算法的骨架,允许子类在不改变算法结构的情况下重定义特定步骤。它是面向对象设计中的多态性的一个示例。 10. **DesignPattern.htm** - 设计模式基础 这个文件可能是对设计...
工厂方法模式是创建型设计模式之一,它定义了一个用于创建对象的接口,但是让子类决定实例化哪一个类。工厂方法让类的实例化推迟到子类。 **示例解析:** 假设每次约会都需要准备一些小礼物,这些礼物可能因人而异...
1. **郑志远的java学习笔记.doc**:这可能是个人的学习心得或者教学笔记,通常会包含Java的基础语法、常用类库、编程技巧等内容。可能涵盖变量、数据类型、控制流、异常处理、类与对象、接口等核心概念。 2. **...
19. **模板方法模式(Template Method)**:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 20. **访问者模式(Visitor)**:表示一个...
【Velocity学习笔记】 Velocity是一个基于Java的模板引擎,它的核心目标是实现Model-View-Controller(MVC)架构,让Web设计师专注于视图设计,而Java开发者负责业务逻辑。通过Velocity,视图模板与Java代码分离,...
21. **模板方法模式(Template Method)**:定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 22. **访问者模式(Visitor)**:表示一个...