模板方法模式
- 模板方法模式: 使用一个抽象类定义算法模板结构,将某些具体算法步骤的实现延迟到子类中进行,使得子类在不改变算法结构的情况下重新定义某些算法的具体实现.算法的调用在抽象类中进行
- 模板方法模式是行为型模式, 基于继承的代码复用
-
模板方法的关键: 子类可以置换父类中的可变部分,但是不可以改变模板方法中实现的顶级逻辑
- 在模板方法模式中定义新的子类时,不是按照控制流程,而是按照责任的思想
- 要考虑子类中对父类中的哪些方法是必须要置换的,哪些是可以置换的,哪些是不能置换的. 通过模板方法可以使得这些责任清晰明朗
-
模板方法模式的应用场景:
- 重要的,复杂的方法可以作为模板方法
- 使用一个类来实现一个算法的不变的逻辑,并将可变的逻辑延迟到子类中进行实现
- 各个子类中的公共行为提取集中到一个父类中,用来避免代码重复
- 控制子类的扩展
模板方法模式示例
- 模板方法模式包含两个角色:
-
抽象模板AbstractTemplate:
- 定义抽象操作的算法模板结构,用于在子类中实现
- 抽象操作也就是基本操作,是一个顶级逻辑的组成步骤
- 定义并实现一个模板方法
- 模板方法是一个具体方法
- 给出了一个顶级逻辑的结构,而逻辑结构的组成步骤在相应的抽象操作中,延迟到子类中实现
- 顶级逻辑结构中也可能会调用一些具体方法
- 定义抽象操作的算法模板结构,用于在子类中实现
-
具体模板ConcreteTemplate:
- 实现抽象模板AbstractTemplate中定义的抽象方法.是一个顶级逻辑的组成步骤
- 每一个抽象模板AbstractTemplate都可以有任意多个具体模板ConcreteTemplate相对应. 每一个具体模板ConcreteTemplate都可以对这些抽象模板AbstractTemplate中顶级逻辑的组成步骤进行不同的实现,从而使得顶级逻辑的实现各有不同
-
抽象模板AbstractTemplate:
-
模板方法模式中的方法: 模板方法和基本方法
-
模板方法:
- 模板方法定义在抽象类中,将多个基本方法操作组合成一个总的算法或者行为
- 一个抽象类可以包含任意多个模板方法, 每一个模板方法可以调用任意多个具体方法
-
基本方法:
- 抽象方法AbstractMethod : 抽象方法由抽象类声明,由具体子类实现
- 具体方法ConcreteMethod : 具体方法由抽象类声明并实现,子类不进行实现或者替换
-
钩子方法HookMethod : 钩子方法由抽象类声明并实现,子类可以进行扩展.
- 一般情况下,抽象类会给出钩子方法的一个空实现作为默认实现
- 钩子方法使得子类不需要给出父类的所有方法实现,因为一个具体的子类通常不需要实现父类中的所有的方法
-
模板方法:
-
模板方式模式实现:
- 分析目标算法,确定能否分解为多个步骤.从各个子类的角度,考虑哪些步骤能够通用,哪些步骤有不同
- 创建一个抽象类并声明一个模板方法和代表算法步骤的一系列的抽象方法. 在模板方法中根据算法的结构依次调用算法步骤,使用final修饰符修饰模板方法以防止子类对模板方法进行重写
- 将子类的共有的方法放到父类中,子类中只需要重写可变的算法逻辑
- 可以考虑在父类中添加钩子方法,默认为空实现,用于子类对算法逻辑进行扩展
- 每一个算法子类都需要新建一个具体的子类,必须实现所有的抽象步骤,可以重写部分可选的扩展步骤
- 模板方法模式Template Method示例
模板方法模式总结
模板方式模式注意点
- 通常情况下,模板方法都要加上final关键字
模板方法模式优点
- 实现反向控制: 父类调用子类的操作,通过子类的具体实现扩展成不同的行为,实现了反向控制,符合开闭原则
- 提高代码的复用性: 将共有的代码放到抽象的父类中,不同的代码实现放在子类中
- 提高了系统的扩展性: 将不同的代码放到不同的子类中,通过对子类的扩展增加新的行为
- 行为由父类控制,子类实现
模板方法模式缺点
- 增加了系统的复杂性: 引入了抽象类,每一个不同的实现都需要一个子类来实现,导致系统中类的个数增加
- 通过子类修改父类的默认步骤实现,可能违反了里氏代换的原则
模板方法模式和工厂模式的区别
模板方法模式
- 模板方法模式基于继承机制,允许在子类中扩展和修改算法相关步骤实现
- 模板方法模式是静态的,是在类层次上进行的
工厂方法模式
- 工厂方法模式是一种特殊的模板方法模式
- 工厂方法可以作为一个大型的模板方法模式中的一个步骤
策略模式
- 策略模式基于组合机制,可以通过对相应的行为提供不同的策略来改变对象的部分行为
- 策略模式是动态的,可以在运行时切换行为.策略模式是在对象层次上进行的