一、模版方法模式概述
在开发中有时会遇到类似的情况,某个方法的实现需要多个步骤,其中有些步骤是固定的,而有些步骤是不固定的,存在可变性。为了提供代码的复用性和灵活性,可以使用模板方法的设计模式。
定义:
模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
二、模板方法模式的结构和实现
2.1 模板方法模式的结构
模板方法模式包含2个角色:
- AbstractClass(抽象类):定义了一些列基本操作并实现了一个模板方法,模板方法用于定义一个算法的框架;
- ConcreteClass(具体子类):是抽象类的子类,用于实现在父类中声明的抽象基本方法以完成子类特定算法的步骤,也可以覆盖在父类中已实现的具体基本方法。
2.2 模板方法模式的实现
以下用一个银行办理业务的案例来进一步学习模版方法模式。
//抽象类
/**
* 抽象模版类
* 银行业务
*/
public abstract class BankBusiness {
/**
* 取号
*/
public void takeNumber(){
System.out.println("取号排队");
}
/**
* 办理具体业务
*/
public abstract void business();
/**
* 评价
*/
public void rating(){
System.out.println("对银行工作人员进行评分");
}
/**
* 来银行办理业务的模版方法
* 此方法中的final关键字可用可不用,
* 如果此方法要求不能被覆盖重写,就加上,
* 否则可以不加
*/
public final void handle(){
takeNumber();
business();
rating();
}
}
//具体子类
/**
* 存款的业务
*/
public class DepositBankBusiness extends BankBusiness{
@Override
public void business() {
System.out.println("办理存款业务");
}
}
/**
* 转账的业务
*/
public class TransferBankBusiness extends BankBusiness{
@Override
public void business() {
System.out.println("办理转账业务");
}
}
/**
* 取款的业务
*/
public class WithdrawalBankBusiness extends BankBusiness{
@Override
public void business() {
System.out.println("办理取款业务");
}
}
//客户端
public class Client {
public static void main(String[] args) {
/**
* 案例需求描述:
* 在银行办理业务一般包含几个基本步骤,首先需要取号排队,然后办理具体业务,最后需要对银行工作人员进行评分。
* 无论具体业务是取款,存款,转账,其基本流程都一样。
* 现使用模版方法模式模拟银行业务办理流程。
*/
//定义银行业务对象
BankBusiness bankBusiness1;
BankBusiness bankBusiness2;
//这里可以根据其他参数来动态实例化对应的具体功能类
bankBusiness1 = new DepositBankBusiness();
bankBusiness2 = new WithdrawalBankBusiness();
//办理银行业务,这里不会因为上面的new出来的类不同而改代码。
bankBusiness1.handle();
bankBusiness2.handle();
}
}
三、模板方法模式的优缺点和适用环境
3.1 模板方法模式的优点
- 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,并且不会改变算法中步骤的的执行次序;
- 模板方法模式是一种代码复用技术,提取公共行为放在父类中;
- 模板方法模式可以实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一个特定步骤是否需要执行;
- 具有良好的可扩展性,更换和新增新的子类很方便,符合单一职责原则和开闭原则。
3.2 模板方法模式的缺点
- 需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时可结合桥接模式进行设计。
3.3 模板方法模式的适用环境
- 一次性实现一个算法的不变部分,并将可变的行为留给子类来实现;
- 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复;
- 需要通过子类来决定父类算法中的某个步骤是否执行,实现子类对父类的反向控制。
【参考文献】:
本文是根据刘伟的《Java设计模式》一书的学习笔记,仅供学习用途,勿做其他用途,请尊重知识产权。
【本文代码仓库】:https://gitee.com/xiongbomy/java-design-pattern.git