思想以自己的言语喂养它自己,而成长起来。 — 泰戈尔
写在前面
模板模式的定义:定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类不改变算法的结构即可重新定义某些算法的特定步骤。
抽象模板类(AbstractClass):定义了一套算法框架。
具体模板类(ConcreteClass):抽象模板类的具体实现。
认识模板
下面通过一个例子来认识模板模式:
中秋节快到了,各大食品厂又要开始做月饼了,做月饼其实是有模板的,只要放入不同的馅料就可以制作出不同口味的月饼了。
1.抽象模板类
因为做月饼是有模板的,所以我们要先定义模板。
/**
* 抽象模板类
*/
public abstract class AbsTemplate {
public abstract void ready();
public abstract void doing();
public abstract void end();
/**
* 该方法使用final修饰,防止算法框架被复写
*/
public final void start() {
ready();
doing();
end();
}
}
2.具体模板类
现在我们通过这个模板来制作不同口味的月饼,我喜欢吃豆沙和菠萝口味的,那么就要使用同一个模板制作两种口味的月饼,也就是要创建两个模板类,分别制作豆沙和玻璃口味的月饼。
/**
* 具体模板类
*/
public class DouShaTemplate extends AbsTemplate {
@Override
public void ready() {
Log.d("豆沙", "准备豆沙馅料");
}
@Override
public void doing() {
Log.d("豆沙", "开始制作豆沙月饼");
}
@Override
public void end() {
Log.d("豆沙", "豆沙月饼制作完成");
}
}
/**
* 具体模板类
*/
public class BoLuoTemplate extends AbsTemplate {
@Override
public void ready() {
Log.d("菠萝", "准备菠萝馅料");
}
@Override
public void doing() {
Log.d("菠萝", "开始制作菠萝月饼");
}
@Override
public void end() {
Log.d("菠萝", "菠萝月饼制作完成");
}
}
3.制作月饼
现在让我们来制作不同口味的月饼。
/**
* 客户端
*/
public class Client {
public Client() {
// 制作豆沙口味月饼
AbsTemplate douSha = new DouShaTemplate();
douSha.start();
// 制作菠萝口味月饼
AbsTemplate boLuo = new BoLuoTemplate();
boLuo.start();
}
}
总结
模板模式的使用场景:
- 多个子类有共有的方法,并且逻辑基本相同时。
- 面对重要,复杂的算法,可以把核心算法设计为模板方法,周边相关细节功能则由各个子类实现。
- 需要通过子类来决定父类算法中的某些步骤是否执行,实现了子类对父类的反向控制。
模板模式的优点:
- 通过把不变的行为搬移到超类,去除了子类中重复的代码。
- 子类实现算法的某些细节,有助于算法的扩展。
模板模式的缺点:
- 每个不同的实现都要定义一个子类,这会导致类的数量的增加,设计更加抽象。