模板方法模式
模板方法模式就是定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
例如:某个特定的应用中具有很多的子任务,每个任务的数据计算步骤几乎都是一致的,只是具体的实现可能存在一些差别,则可以定义一个超类,在超类中定义所有任务的计算流程,然后子类去实现特殊的步骤。代码如下所示:
package com.factory.templetemethod;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
SuperApp app1 = new ConcreteApp1();
app1.invoke();
SuperApp app2 = new ConcreteApp2();
app2.invoke();
}
}
abstract class SuperApp {
//基本方法
public abstract List<String> readDataFromDB();
//基本方法
public abstract List<Integer> computeData(List<String> list);
//基本方法
public abstract void storeResult(List<Integer> result);
//模板方法
public void invoke() {
List<String> data = readDataFromDB();
List<Integer> result = computeData(data);
storeResult(result);
}
}
class ConcreteApp1 extends SuperApp {
public List<String> readDataFromDB() {
return null;
}
public List<Integer> computeData(List<String> list) {
System.out.println("ConcreteApp1");
return null;
}
public void storeResult(List<Integer> result) {
}
}
class ConcreteApp2 extends SuperApp {
public List<String> readDataFromDB() {
return null;
}
public List<Integer> computeData(List<String> list) {
System.out.println("ConcreteApp2");
return null;
}
public void storeResult(List<Integer> result) {
}
}
上述代码中,我们在超类SuperApp中定义了任务是计算步骤,分别是
readDataFromDB()
computerData()
storeResult()
这三个操作叫做基本操作,然后定义了一个模板方法
//模板方法 public void invoke() { List<String> data = readDataFromDB(); List<Integer> result = computeData(data); storeResult(result); }
这个方法定义了子类任务的计算步骤。
类图结构如下所示:
模板方法模式的优点
1. 封装不变部分,扩展可变部分。把认为不变部分的算法封装到父类实现,而可变部分的则通过继承来继续扩展。
2.提取公共部分代码,便于维护。
3.行为由父类控制,子类实现。基本方法是由子类实现的,因此子类可以通过扩展的方式增加相应的功能,符合开闭原则。
模板方法模式的缺点
按照设计习惯,抽象类负责声明最抽象,最一般的事物属性和方法,实现类完成具体的事物属性和方法。但是模板方法却颠倒了,抽象类定义了部分抽象方法,由子类实现,子类执行的结果影响了父类的结果,在复杂项目中会带来代码阅读的难度。
模板方法模式使用场景
1.多个子类有公有的方法,并且逻辑基本相同。
2.重要、复杂的算法,可以把核心算法设计成模板方法,周边的相关细节功能则由各个子类实现。
3.重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。