模板顾名思义就是已经按照固定格式进行总结的一种结构形式。生活中,制造瓷器的过程就是一种模板的体现。制造陶瓷要先制作模具,然后再使用不同颜色的陶土,在模具中炼制,就可以炼制出形状一致,但花色不同的瓷器。这个生活中的例子就是模板方法模式的一个类比。在模板方法模式中,我们也是定义一系列操作的步骤,对于暂时无法确定的步骤,就交给子类进行实现。这样,子类就能够通过更加完善的步骤生成对象。
模板方法模式
模板方法模式(Template Method)的定义:定义一个操作中的算法“骨架”,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板方法模式在实际开发中的应用场景并没有很多,主要是因为我们一般不在抽象类中定义逻辑行为。而这个设计模式在抽象类中定义逻辑行为的执行顺序。
模板方法模式的结构
模板方法模式包含以下结构:
- 抽象模板(AbstractClass):抽象模板定义算法的“骨架”,它实现了模板方法,也声明了在模板方法中所使用到的抽象方法。
- 具体模板(ConcreteClass):具体模板实现抽象模板提供的抽象方法。
模板方法的实际应用场景
- 计算具有复杂数学属性的对象:例如加密算法
- 具有强步骤性的场景:例如签署电子协议,协议可能会经常改变,我们就可以将经常修改的协议抽象为模板。
示例
我们来实现一个应用协议的签署流程。假设一个应用的协议需要签署三个部分:1)应用隐私协议。2)用户操作协议。3)应用免责声明。我们使用模板方法来实现这个协议的签署。
首先,我们定义一个协议的抽象模板。抽象模板,包含签署的所有协议信息,并提供一个抽象方法以供子类扩展。
Policy.java
package com.yeliheng.templatemethod;
/**
* 抽象模板
*/
public abstract class Policy {
public void TemplateMethod() {
agreePrivacyPolicy();
agreeOperationPolicy();
disclaimer();
if(agreeResult()) {
System.out.println("签署成功!");
}else {
System.out.println("签署失败!");
}
}
//隐私协议
public void agreePrivacyPolicy() {
System.out.println("您正在签署[隐私协议],以下是协议内容:(1)...(2)...(3)...");
}
//操作协议
public void agreeOperationPolicy() {
System.out.println("您正在签署[操作协议],以下是协议内容:(1)...(2)...(3)...");
}
//应用免责声明
public void disclaimer() {
System.out.println("[免责声明]: (1)...(2)...(3)...");
}
public abstract boolean agreeResult();
}
抽象模板中,我们定义了签署协议的具体步骤,并定义TemplateMethod()方法来将步骤按顺序执行。当agreeResult()方法返回值为true时,我们则认为协议签署成功。
接下来,我们来拓展子类,在子类中写入签署协议的具体操作。
Sign.java
package com.yeliheng.templatemethod;
/**
* 签署协议
*/
public class Sign extends Policy{
@Override
public boolean agreeResult() {
//同意所有协议
return true;
}
}
Sign类即我们的具体模板类。在Sign类中,我们进行了协议的签署,为了演示方便,我们直接让agreeResult()返回true以代表协议的成功签署。
最后我们执行程序,看看最终的输出结果。
最终输出结果如下图所示:
模板方法模式的优缺点
优点
- 模板方法模式只封装了不变的部分,可变的部分以抽象方法的方式提供,方便扩展。
- 模板方法模式符合开闭原则,因为部分方法由子类进行实现,子类可通过扩展方式增加功能。
缺点
- 过度使用模板方法模式会造成子类数量的大量增长,提升系统复杂度。
总结
模板方法模式能够将可变的,不确定的过程交给子类处理,将固定的步骤封装在抽象模板中,供子类调用。在本文中,通过签署应用协议的例子详解模板方法模式。
本文示例的完整源代码参见:Github