概述
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成。模板方法模式使得子类可以不改变整个算法的结构即可重定义该算法的某些特定步骤。
模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术,没有关联关系。因此在模板方法模式的类结构图中,只有继承关系。
核心设计要点
AbstractClass:抽象类,定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现
ConcreteClass:实现实现父类所定义的一个或多个抽象方法。
模板方法应用场景
有多个子类共有的方法,且逻辑相同。
重要的、复杂的方法,可以考虑作为模板方法。
聚合支付回调、Servlet请求
优点
模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
缺点
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
应用案例
说把大象塞进冰箱需要几步,首先把冰箱门打开,把大象塞进去,把冰箱门关上,搞定
实现案例
定义模板方法
/**
* 定义模板方法
*
* @author ext.liuyan10
* @date 2021/2/7 14:48
*/
public abstract class Template {
/**
* 打开冰箱
*/
protected abstract void openRefrigerator();
/**
* 关上冰箱
*/
protected abstract void closeRefrigerator();
/**
* 把动物装进去
*/
protected abstract void putAnimal();
/**
* 开始装动物
*/
public void run() {
this.openRefrigerator();
this.putAnimal();
this.closeRefrigerator();
}
}
把大象装进去
/**
* 实现具体行为
*
* @author ext.liuyan10
* @date 2021/2/7 14:49
*/
public class TemplateImpl extends Template {
@Override
protected void openRefrigerator() {
System.out.println("将冰箱门打开");
}
@Override
protected void closeRefrigerator() {
System.out.println("将冰箱门关上");
}
@Override
protected void putelephant() {
System.out.println("把大象装进去");
}
}
把猴子装进去
/**
* 实现具体行为
*
* @author ext.liuyan10
* @date 2021/2/7 14:49
*/
public class TemplateImpl01 extends Template {
@Override
protected void openRefrigerator() {
System.out.println("将冰箱门打开");
}
@Override
protected void closeRefrigerator() {
System.out.println("将冰箱门关上");
}
@Override
protected void putAnimal() {
System.out.println("把猴子装进去");
}
}
运行案例
/**
* @author ext.liuyan10
* @date 2021/2/7 14:50
*/
public class TemplateApp {
public static void main(String[] args) {
Template template = new TemplateImpl();
template.run();
TemplateImpl01 templateImpl01 = new TemplateImpl01();
templateImpl01.run();
}
}
运行结果
Connected to the target VM, address: '127.0.0.1:50884', transport: 'socket'
将冰箱门打开
把大象装进去
将冰箱门关上
将冰箱门打开
把猴子装进去
将冰箱门关上
Disconnected from the target VM, address: '127.0.0.1:50884', transport: 'socket'
Process finished with exit code 0