定义
模版方法模式:定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。(Template Method Pattern: 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.
简单来说:定义一个父类,由父类定义接口规范,然后不同的行为在子类中实现。
通用类图

可以看到模版方法模式非常简单,抽象类方法分为两类:
基本方法:基本方法也叫基本操作,是由子类实现的方法,并且在模版方法中被调用
模版方法:可以有一个或几个,一般是一个具体方法,也就是一个模版,实现具体的调用逻辑
类图实现
使用父类实现模版方法
public class AbstractClass {
func doSomething() {}
func doAnything() {}
func hook() -> Bool { // 钩子方法
return true
}
func templateMethod() {
if hook() { doSomething() }
doAnything()
}
}
class ConcreteClass1: AbstractClass {
// 实现基本方法
override func doSomething() {
//业务逻辑处理
print("ConcreteClass1 doSomething")
}
override func doAnything() {
//业务逻辑处理
print("ConcreteClass1 doAnything")
}
override func hook() -> Bool {
return false
}
}
class ConcerteClass2: AbstractClass {
// 实现基本方法
override func doSomething() {
//业务逻辑处理
print("ConcreteClass2 doSomething")
}
override func doAnything() {
//业务逻辑处理
print("ConcreteClass2 doAnything")
}
}
使用协议实现模版方法
protocol AbstractProtocol {
func doSomething()
func doAnything()
func hook() -> Bool
func templateMethod()
}
extension AbstractProtocol {
func hook() -> Bool { // 钩子方法
return true
}
func templateMethod() {
if hook() { doSomething() }
doAnything()
}
}
class ConcreteClass1: AbstractProtocol {
// 实现基本方法
func doSomething() {
//业务逻辑处理
print("ConcreteClass1 doSomething")
}
func doAnything() {
//业务逻辑处理
print("ConcreteClass1 doAnything")
}
func hook() -> Bool {
return false
}
}
class ConcerteClass2: AbstractProtocol {
// 实现基本方法
func doSomething() {
//业务逻辑处理
print("ConcreteClass2 doSomething")
}
func doAnything() {
//业务逻辑处理
print("ConcreteClass2 doAnything")
}
}
简单使用
let class1 = ConcreteClass1()
let class2 = ConcerteClass2()
class1.templateMethod()
class2.templateMethod()
//ConcreteClass1 doAnything
//ConcreteClass2 doSomething
//ConcreteClass2 doAnything
模版方法模式的优点
封装不变部分,扩展可变部分。即把认为不变部分的算法封装到父类实现,而可变部分的则可以通过继承来继续扩展
提取公共部分代码,便于维护
行为由父类控制,子类实现
模版方法模式的缺点
按照平时的设计习惯,抽象类负责最抽象、最一般的事物属性和方法,实现类完成具体的事物属性和方法,但是模版方法模式却颠倒了,抽象类定义了部分抽象方法,由子类实现,子类执行的结果影响了父类的结果,也就是子类对父类产生了影响,这在复杂的项目中,会带来代码阅读的难度
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
模版方法模式的使用场景
多个子类有公有的方法,并且基本逻辑相同
重要 、复杂的算法,可以把核心算法设计为模版方法,相关的细节功能则由各个子类实现
重构时,模版方法模式就是经常使用的模式,把相同的代码抽取到父类中,然后通过钩子方法(即抽象类中添加的新方法,该方法用于在模版方法中规避某些操作)约束其行为