爱学it学无止境
模版方法模式角色如下:
⨳ AbstractClass(抽象类):定义了一个模板方法(Template Method),其中包含了算法的框架及具体步骤的声明,部分步骤可以是抽象方法,由具体子类实现。
⨳ ConcreteClass(具体子类) :继承自抽象类,并实现了其中定义的抽象方法,完成算法中具体步骤的实现。
UML
类图结构很简单,就一个继承关系,模板方法模式的重点在 AbstractClass
(抽象类)上,AbstractClass
由一个模板方法和若干个基本方法构成:
▪ 模板方法:定义了一套算法的骨架,按某种顺序调用其包含的基本方法。
▪ 基本方法:是算法骨架/流程的某些步骤进行具体实现,包含以下几种类型:
▪ ▪ 抽象方法:在抽象类中声明,必须由具体子类实现。
▪ ▪ 具体方法:在抽象类中已经实现,具体子类中可以选择重写它。
▪ ▪ 钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。
基本实现
抽象类 Abstract Class
AbstractClass
是抽象类,其实也就是一抽象模板,定义并实现了一个模版方法。这个模版方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
public abstract class AbstractClass {
// 模板方法
public final void templateMethod() {
abstractMethod(); // 步骤1
concreteMethod(); // 步骤2
emptyMethod(); // 步骤3
if(judgeMethod()){ // 步骤4
System.out.println("任务完成");
}
}
// 抽象方法,子类必须实现
protected abstract void abstractMethod();
// 具体方法,子类选择性实现
protected void concreteMethod(){
System.out.println("具体方法完成步骤2");
}
// 钩子方法(空方法),子类选择性实现
protected void emptyMethod(){
}
// 钩子方法(判断方法),子类选择性实现
protected boolean judgeMethod(){
return false;
}
}
具体子类 ConcreteClass
ConcreteClass
,实现父类所定义的一个或多个抽象方法。每一个 AbstractClass
都可以有任意多个 ConcreteClass
与之对应,而每一个 ConcreteClass
都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
▪ 具体子类A
具体子类A给出了抽象方法的具体实现,并且重写判断钩子方法:
public class ConcreteClassA extends AbstractClass{
@Override
protected void abstractMethod() {
System.out.println("ConcreteClassA 完成步骤1");
}
@Override
protected boolean judgeMethod(){
return true;
}
}
▪ 具体子类B
具体子类B给出了抽象方法的具体实现,并且重写空实现的钩子方法:
public class ConcreteClassB extends AbstractClass{
@Override
protected void abstractMethod() {
System.out.println("ConcreteClassB 完成步骤1");
}
@Override
protected void emptyMethod(){
System.out.println("ConcreteClassB 完成步骤3");
}
}
客户端 Client
AbstractClass template = new ConcreteClassA();
template.templateMethod();
System.out.println("*****************");
template = new ConcreteClassB();
template.templateMethod();
输出结果如下:
ConcreteClassA 完成步骤1
具体方法完成步骤2
任务完成
*****************
ConcreteClassB 完成步骤1
具体方法完成步骤2
ConcreteClassB 完成步骤3
ConcreteClassA
和 ConcreteClassB
的算法骨架相同,但具体个别步骤不同。
这里需要注意的是,钩子方法可以是空方法,可以是判断方法,通过钩子方法的重写可以将模板方法(templateMethod
)中的某个步骤移除或加入。