目录
模板方法模式【Template Method Pattern】, 什么是模板方法模式?核心思想?结构?优缺点?模板方法实现案例?
什么是模板方法模式?
**模板方法模式(Template Method Pattern)**是一种行为型设计模式,它定义了一个操作中的算法的骨架,而将一些步骤的具体实现延迟到子类中。通过模板方法模式,子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。
模板方法模式核心思想
模板方法模式的核心思想是将算法中的不变部分和可变部分分离开。不变部分作为模板方法在父类中定义,而可变部分则由子类通过覆盖具体方法来实现。这样,父类控制算法的整体流程,而子类则决定某些步骤的具体实现细节。
模板方法模式结构
(1)抽象类(Abstract Class)
定义了算法的骨架,并包含一个或多个抽象方法,这些方法由子类实现。
包含模板方法(通常是一个 final 方法),它定义了算法的基本步骤,并依赖子类实现某些步骤。
(2)具体子类(Concrete Class)
继承自抽象类,实现父类中的抽象方法,完成模板中定义的具体步骤。
模板方法模式优缺点
优点
(1)复用代码
模板方法在父类中实现了算法的公共部分,子类只需实现特定步骤,避免代码重复。
(2)遵循开闭原则
算法的骨架是固定的,子类可以通过重写部分方法来扩展功能,且不需要修改模板方法的结构。
(3)灵活性和扩展性
通过增加新的子类,可以很方便地扩展新的算法或步骤实现,而不需要修改父类的代码。
缺点:
(1)增加类的复杂性
引入了抽象类和子类,可能导致类的数量增多,代码结构更加复杂。
(2)限制子类的自由
子类必须遵循父类定义的模板方法流程,不能改变整体流程顺序。
模板方法模式应用场景
(1)算法步骤固定但实现不同的场景
当一个操作的执行步骤是固定的,但是步骤的具体实现可能有所不同。比如文档生成、游戏的关卡逻辑等。
(2)避免代码重复
如果多个子类中有相同的逻辑部分,可以将这部分逻辑上移到父类中,通过模板方法模式避免代码重复。
(3)流程控制
当一个算法的整体流程固定,但是某些部分可以由子类来定制时,模板方法模式非常合适。例如框架中的钩子方法就是这种思想的体现。
模板方法实现案例
1、定义一个车辆模型(抽象)
package com.uhhe.common.design.templatemethod;
/**
* Hummer Model是悍马车辆模型的意思,不是悍马美女车模
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 16:36
*/
public abstract class HummerModel {
/**
* 首先,这个模型要能够被发动起来,别管是手摇发动,还是电力发动,反正是要能够发动起来,那这个实现要在实现类里了
*/
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();
}
/**
* 钩子方法,默认喇叭是会响的
*
* @return 是否会响
*/
protected boolean isAlarm() {
return true;
}
}
2、实现类H1、H2,具体子类(Concrete Class)
H1
package com.uhhe.common.design.templatemethod;
/**
* 悍马车是每个越野者的最爱,其中H1最接近军用系列
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 17:35
*/
public class HummerH1Model extends HummerModel {
/**
* 是否要响喇叭
*/
private boolean alarmFlag = true;
@Override
public void alarm() {
System.out.println("悍马H1鸣笛...");
}
@Override
public void engineBoom() {
System.out.println("悍马H1引擎声音是这样在...");
}
@Override
public void start() {
System.out.println("悍马H1发动...");
}
@Override
public void stop() {
System.out.println("悍马H1停车...");
}
@Override
protected boolean isAlarm() {
return this.alarmFlag;
}
/**
* 要不要响喇叭,是有客户的来决定的
*
* @param isAlarm 是否响喇叭
*/
public void setAlarm(boolean isAlarm) {
this.alarmFlag = isAlarm;
}
}
H2
package com.uhhe.common.design.templatemethod;
/**
* 悍马H2
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 17:33
*/
public class HummerH2Model extends HummerModel {
@Override
protected void alarm() {
System.out.println("悍马H2鸣笛...");
}
@Override
protected void engineBoom() {
System.out.println("悍马H2引擎声音是这样在...");
}
@Override
protected void start() {
System.out.println("悍马H2发动...");
}
@Override
protected void stop() {
System.out.println("悍马H1停车...");
}
/**
* 默认没有喇叭的
*/
@Override
protected boolean isAlarm() {
return false;
}
}
3、模版方法模式使用
package com.uhhe.common.design.templatemethod;
/**
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 17:35
*/
public class Client {
/**
* 模板方法模式【Template Method Pattern】
* <p>
* 下模板方法模式,模板方法模式就是在模板方法中按照一个的规则和顺序调用基本方法,
* 具体到上面那个例子就是 run 方法按照规定的顺序(先调用 start,然后再调用 engineBoom,再调用alarm,最后调用 stop)
* 调用本类的其他方法,并且由 isAlarm 方法的返回值确定 run 中的执行顺序变更
* <p>
* 模板方法在一些开源框架中应用很多,它提供了一个抽象类,然后开源框架写了一堆子类
* 如果需要扩展功能,可以继承了这个抽象类,然后修改 protected 方法,再然后就是调用一个类似 execute 方法,
* 就完成你的扩展开发,确实是一种简单的模式。
*/
public static void main(String[] args) {
// 客户开着H1型号,出去遛弯了
HummerH1Model h1 = new HummerH1Model();
h1.setAlarm(true);
// 汽车跑起来了
h1.run();
// H2型号的悍马跑起来
HummerH2Model h2 = new HummerH2Model();
h2.run();
}
}
总结:
模板方法模式通过定义算法的骨架并延迟某些步骤到子类实现,使得算法的复用性和灵活性得以提升。它是面向对象设计中的一种常见模式,特别适合那些算法结构相对稳定,但某些步骤可以变化的场景。