顾名思义,模板方法模式就是在抽象类里建立一个模板方法,模板方法里面建立一定的规则,用来约束一整套流程或者行为,抽象出可变的方法,供不同的实现类进行不同的实现,提取出不可变的方法,直接在抽象类里实现,通过子类继承父类的形式,复用这套模板。其中模板方法通常定义为final,防止使用者改变其规则。
接着拿洗澡举个例子:
脱衣服(不可变)
打开开关用水淋湿(不可变)
使用清洁用品(可变)
冲洗干净(不可变)
擦干(可变,也可能自然晾干…)
穿衣服(不可变)
这里只讲淋浴,不讲泡澡,你要是非说第二步还能泡澡那就是抬杠。
接着我们用代码来体现一下:
/*
* 首先是定义抽象的模板类
*/
public abstract class ShowerTemplate{
public final void shower(){
takeOffClothes();
beginShower();
useCleaningProducts();
dry();
wearClothes();
}
private void takeOffClothes(){
System.out.println("脱掉衣服准备洗澡");
}
private void beginShower(){
System.out.println("开始淋浴");
}
//使用清洁用品
protected abstract void useCleaningProducts();
private void rinse(){
System.out.println("冲洗干净");
}
//使用各种方法让身体变干
protected abstract void dry();
private void wearClothes(){
System.out.println("穿上衣服走人");
}
}
然后进行不同的实现,比如有些人喜欢用香皂清洁,还用搓澡巾:
public class Shower1 extends ShowerTemplate {
@Override
protected void useCleaningProducts() {
System.out.println("使用香皂清洁并用澡巾搓澡");
}
@Override
protected void dry() {
System.out.println("使用浴巾擦干");
}
}
有些人使用沐浴露,并自然晾干:
public class Shower2 extends ShowerTemplate {
@Override
protected void useCleaningProducts() {
System.out.println("使用沐浴露洗洗");
}
@Override
protected void dry() {
System.out.println("自然晾干");
}
}
调用:
public class Test {
public static void main(String[] args){
ShowerTemplate shower1 = new Shower1();
shower1.shower();
System.out.println("--------------------");
ShowerTemplate shower2 = new Shower2();
shower2.shower();
}
}
输出结果:
脱掉衣服准备洗澡
开始淋浴
使用香皂清洁并用澡巾搓澡
冲洗干净
使用浴巾擦干
穿上衣服走人
--------------------
脱掉衣服准备洗澡
开始淋浴
使用沐浴露洗洗
冲洗干净
自然晾干
穿上衣服走人
总结:
模板方法模式是23种设计模式里相对来说比较简单的一种模式,通过子类继承父类并且合理的设置访问权限修饰符,达到约束子类行为的效果,其中使用final修饰约束流程的方法,使其不能被恶意重写修改。
优点:提取出公共代码减少代码重复编写,开放出可变的部分自由创造,父类约束子类流程便于控制。
缺点:每种不同的实现都要重新添加一个类,比如有人用香皂洗澡并自然晾干,就需要再添加一个类,反而造成了代码的大量增加。
所以需要根据实际情况来使用设计模式,如果多个子类有很多共有的方法和相同的逻辑,就可以考虑使用模板方法模式。