目录
一、模板方法模式的介绍
1、定义
模板方法模式定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法模式的角色划分如下:
- 抽象模板角色(Abstract Template):该角色定义一个或多个抽象操作,以便让子类实现;这些抽象操作是基本操作,是一个顶级逻辑的组成步骤,还需要顶一个并实现一个或几个模板方法,这些模板方法一般是具体方法,即一个框架,实现对基本方法的调度,完成固定的逻辑。
- 具体模板角色(Concrete Template):该角色实现抽象模板中定义的一个或多个抽象方法,每一个抽象模板角色都可以由任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法的不同实现,从而使得顶级逻辑的实现各不相同。
模板方法模式的类图如下:
2、使用场景
- 多个子类有公共方法,并且逻辑相同时。
- 可以把重要的、复杂的、核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
- 重构时,模板方法模式是一个经常使用的模式,将相同的代码抽取到父类中。
3、优缺点
(1)优点
- 封装不变的部分,扩展可变的部分。把认为不变部分的算法封装到父类中实现,而可变部分的则可以通过继承来继续扩展。
- 提取公共部分代码,便于维护。
- 行为由父类控制,子类实现。
(3)缺点
- 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更为抽象。
- 父类中的抽象方法由子类实现,子类的执行结果会影响到父类的结果。因为一般的设计习惯,由抽象类申明最抽象、最一般的事务属性和方法,实现类完成具体的事物属性和方法,但是模板方法模式正好相反。
二、模板方法模式的实现
场景描述:老师和学生去超市去买东西,他们都要先浏览货物,找到自己中意的,然后加入购物车,最后去柜台结账。整个过程的UML如下:
代码实现如下:
抽象模板类:
/**
* 抽象模板类
*/
public abstract class SuperMarket {
/**
* 浏览货物
*/
public abstract void browseGoods();
/**
* 加入购物车
*/
public abstract void addToCart();
/**
* 结账
*/
public abstract void count();
/**
* 逛超市的框架流程:看货物;加入购物车;结账
*/
public final void shop(){
browseGoods();
addToCart();
count();
}
}
具体模板角色:
public class Student extends SuperMarket{
@Override
public void browseGoods() {
System.out.println("先去水果区看看");
}
@Override
public void addToCart() {
System.out.println("买一斤苹果,一个大柚子");
}
@Override
public void count() {
System.out.println("用微信结账");
}
}
public class Teacher extends SuperMarket{
@Override
public void browseGoods() {
System.out.println("先去生活用品区看看");
}
@Override
public void addToCart() {
System.out.println("买一个靠枕、一瓶洗衣液");
}
@Override
public void count() {
System.out.println("用支付宝结账");
}
}
测试类:
public class Client {
public static void main(String[] args) {
SuperMarket s1 = new Student();
s1.shop();
System.out.println("=========");
SuperMarket s2 = new Teacher();
s2.shop();
}
}