模板方法模式(Template Method)
定义一个操作算法的骨架,将一些步骤推迟到子类中完成。模板方法使得子类可以不改变一个算法结构即可定义该算法的某些特定步骤。
在GoF23种设计模式中,属于行为型模式( Behavioral Patterns)
。
以我们点外卖支付为例。支付时可以选余额宝、招商银行、工商银行支付。虽然不同支付渠道的对接是不一样的,但是支付的流程是统一的。
下单 -> 支付 -> 抽奖 -> 配送
(彩蛋:如果使用余额宝,中奖品质提升)
这里我们就可以用模板方法模式,将下单
、抽奖
、配送
放入模板中定义好。将支付
放入到子类中实现。
- 优点
- 提高系统复用性
- 增强系统拓展性
- 符合开闭原则
- 缺点
- 增加了系统复杂度
- 模板类不易拓展
- 使用场景
- 当一个流程既有共性部分又有差异部分时,建议使用模板方法
实例
角色说明
- AbstractClass
- 抽象类,定义总流程
- ContentClass
- 具体实现类,定义流程中的特殊操作
- Client
- 使用者
举例
- AbstractPay.java
public abstract class AbstractPay {
protected final void process() {
order();
pay();
if (isAliPay()) {
System.out.println("中奖品质提升了");
}
draw();
deliver();
}
private void order() {
System.out.println("下单啦");
}
abstract void pay();
//钩子函数
protected boolean isAliPay() {
return false;
}
private void draw() {
System.out.println("恭喜你,中奖了");
}
private void deliver() {
System.out.println("配送到家啦,请开门");
}
}
- AliPay.java
public class AliPay extends AbstractPay{
@Override
void pay() {
System.out.println("已使用余额宝支付");
}
@Override
protected boolean isAliPay() {
return true;
}
}
- CmbPay.java
public class CmbPay extends AbstractPay{
@Override
void pay() {
System.out.println("已使用招商银行支付");
}
}
- Client.java
public class Client {
public static void main(String[] args) {
AbstractPay alipay = new AliPay();
alipay.process();
System.out.println("\n又下一单\n");
AbstractPay cmb = new CmbPay();
cmb.process();
}
}
- output
下单啦
已使用余额宝支付
中奖品质提升了
恭喜你,中奖了
配送到家啦,请开门
又下一单
下单啦
已使用招商银行支付
恭喜你,中奖了
配送到家啦,请开门
实例
code:java.lang.ClassLoader
- ClassLoader.java
public abstract class ClassLoader {
//省略...
//主流程
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
//递归让父类加载该类
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
//用于重写的钩子函数
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
//省略...
}
总结
通过模板方法模式,将会很大程度上的提高系统拓展性和代码复用性。如果在设计中遇到有很多共性的处理方式,那么差异性就可以通过模板方法来弥补。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名,转载请标明出处
最后编辑时间为: