1 概述
模板方法模式(Template Method Pattern)是一种很常见的行为模式。在超类/抽象类中创建一个模板方法,方法中定义一个算法步骤或框架,让子类在不修改主结构的情况下,重写其中的子步骤。
2 模板方法模式
假如存在一系列对象的方法,他们的步骤是大体一致的,区别只是其中的一个子步骤。这种情况会导致大量重复冗余的代码,当公共部分需要改变时,不得不修改所有相关的对象。如果用模版方法模式改造,可以简化逻辑:将其中不变的部分抽离出来,作为一个模板方法,然后让子类只实现差异化的部分代码。
比如,前面举过的例子中,网上购物结算可以有多种途径,支付宝,微信等等,所以对于“网上购物”,运用模板方法模式的思想,便可以将挑选商品,加入购物车,提交订单,支付结算这几个步骤,定义成模板方法。其中,前面三个步骤是通用的,最后一个方法,留给子类根据不同的支付方式去实现自己的逻辑。
一般情况下,模板方法应该定义为final
,因为它包含了算法的框架,不应该被子类覆盖重写。类似的,需要子类重写的差异化方法,需要定义为abstract
。
3 案例
看一个案例加深理解。做披萨的一般顺序是:做披萨皮,加浇头,烘焙。披萨是什么口味,完全看浇头是什么,所以,我们可以用模版方法模式来“制作披萨”:
public abstract class PizzaCook {
public final void bakePizza() {
processCrust();
processTopping();
bake();
System.out.println("Pizza is now baked!!!");
}
private void processCrust() {
System.out.println("Crust is ready...");
}
private void bake() {
System.out.println("Putting the pizza to oven...");
};
protected abstract void processTopping();
}
public class FruitPizzaCook extends PizzaCook {
[@Override](https://my.oschina.net/u/1162528)
protected void processTopping() {
System.out.println("Putting some fruit on the Pizza...");
}
}
public class BaconPizzaCook extends PizzaCook {
[@Override](https://my.oschina.net/u/1162528)
protected void processTopping() {
System.out.println("Putting the bacon on the Pizza...");
}
}
public class Test {
public static void main(String[] args) {
PizzaCook fruitPizzaCook = new FruitPizzaCook();
fruitPizzaCook.bakePizza();
System.out.println("--------------");
PizzaCook baconPizzaCook = new BaconPizzaCook();
baconPizzaCook.bakePizza();
}
}
输出:
Crust is ready...
Putting some fruit on the Pizza...
Putting the pizza to oven...
Pizza is now baked!!!
--------------
Crust is ready...
Putting the bacon on the Pizza...
Putting the pizza to oven...
Pizza is now baked!!!
父类中定义了披萨的制作步骤,作为子类,只需要实现processTopping()
方法。模板方法模式省去了很多重复代码,方便了代码重用。当公共部分(processCrust()
/bake
)需要改动时,只需要改动父类即可。
JDK
中,所有的List
都继承了AbstractList,所有的Set
都继承了AbstractSet,所有的Map
都继承了AbstractMap,模板方法模式在这三个类中得到了很好的运用。
4 总结
模板方法模式通过将方法的步骤抽象分离,封装不变部分,扩展可变部分,减少了冗余代码,方便了维护。
来源:oschina
链接:https://my.oschina.net/u/2411391/blog/4296318