模板方法模式
定义
定义一个操作中算法的骨架(或称顶级逻辑),将一些步骤的执行延迟到其子类中,使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
(Define the skeleton of an algorithm in an operation , deferring some steps to subclasses . Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure .)
模板方法模式的通用类图如下所示:
![](https://img.haomeiwen.com/i4625756/3110f8625398bf65.jpg)
上图中所涉及的角色:
- 抽象类(AbstractClass):定义了一到多个的抽象方法,以供具体的子类来实现它们;而且还要实现一个模板方法,来定义一个算法的骨架。该方法不仅调用前面的抽象方法,也可调用其他的操作,只要能完成自己的使命。
- 具体类(ConcreteClass):实现父类的抽象方法以完成算法中的特定子类相关的步骤。
模板方法模式中的AbstractClass叫做抽象模板,它的方法可以分为两类:
- 基本方法:也称基本操作,是由子类实现的方法,并且在模板方法被调用。
- 模板方法:可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑。
注意:
- 为了方法恶意操作,一般模板方法都加上final关键字,不允许被覆写。
- 抽象模板中的基本方法尽量设计为protected类型,符合迪米特法则,不需要暴露的属性或方法尽量不要设置为protected类型。实现类若非必要,尽量不要扩大父类中的访问权限。
示例代码如下所示:
//抽象模板类
public abstract class Model{
protected abstract void start();
protected abstract void stop();
protected abstract void alarm();
protected abstract void engineBoom();
final public void run(){
this.start();
this.engineBoom();
this.alarm();
this.stop();
}
}
public class H1Model extends Model{
protected abstract void start(){
}
protected abstract void stop(){
}
protected abstract void alarm(){
}
protected abstract void engineBoom(){
}
}
public class H1Model extends Model{
protected abstract void start(){
}
protected abstract void stop(){
}
protected abstract void alarm(){
}
protected abstract void engineBoom(){
}
}
优缺点
优点:
- 封装不变部分,扩展可变部分:把认为是不变部分的算法封装到父类实现,而可变部分的则可以通过继承来继续扩展。
- 提取公共部分代码,便于维护
- 行为由父类控制,子类实现
缺点:
- 虽然使用模板方法模式可以很自由地实现具体的算法,但如果算法的骨架有改变的话,则需要改变抽象类。
使用场景:
- 多个子类有公有的方法,并且逻辑基本相同。
- 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
- 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。
扩展
父类怎么调用子类的方法?
- 把子类传递到父类的有参构造中,然后调用;
- 使用反射的方式调用;
- 父类调用子类的静态方法。
但是在项目中并不允许这么使用,使用模板方法模式就可以产生一样的效果。
UML图示如下所示:
![](https://img.haomeiwen.com/i4625756/9f5801b6bfe0aaf1.jpg)
扩展的代码如下:
//抽象模板类
public abstract class Model{
protected abstract void start();
protected abstract void stop();
protected abstract void alarm();
protected abstract void engineBoom();
final public void run(){
this.start();
this.engineBoom();
if(this.isAlarm()){
this.alarm();
}
this.stop();
}
//钩子方法
protected boolean isAlarm(){
return true;
}
}
public class H1Model extends Model{
private boolean alarmFlag = true;
protected abstract void start(){
}
protected abstract void stop(){
}
protected abstract void alarm(){
}
protected abstract void engineBoom(){
}
//钩子方法
protected boolean isAlarm(){
return this.alarmFlag;
}
//要不要执行alarm()方法由客户来决定
public void setAlarm(boolean isAlarm){
this.alarmFlag = isAlarm;
}
}
public class H1Model extends Model{
protected abstract void start(){
}
protected abstract void stop(){
}
protected abstract void alarm(){
}
protected abstract void engineBoom(){
}
//钩子方法
protected boolean isAlarm(){
return false;
}
}
欢迎大家关注我的微信公众号!
![](https://img.haomeiwen.com/i4625756/beb034404febc1f2.jpg)
网友评论