版权声明:需要引用、发表的朋友请与本人联系 https://blog.csdn.net/pbrlovejava/article/details/84667829
文章目录
更多关于设计模式的文章请点击:设计模式之禅(0)-目录页
模板方法模式是23种设计模式中的一种,与其说它是一种设计模式,我更加偏向于认为它是一种设计的思想。
一、模板方法模式的定义
模板方法模式(Template Pattern
),一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
二、模板方法模式的使用
我们又要举动物们的例子了:在动物商店买动物会经过一系列过程:
1、获得动物
2、把动物装起来
3、把动物送给你
这3个步骤可抽取成一个模板方法(Template Method
)getAnimals,如以下代码:
public class AnimalShop {
//获取动物的模板方法
public void getAnimals(){
getAnimal();
packageAnimal();
giveAnimal();
}
public void getAnimal(){//dosomething}
public void packageAnimal(){//dosomething};
public void giveAnimal(){//dosomething};
}
当我们需要有多个不同的动物商店时,我们可以很容易地想到将以上方法抽取出来,使动物商店变成一个超类:
public abstract class AnimalShop {
//获取动物的模板方法
public void getAnimals(){
getAnimal();
packageAnimal();
giveAnimal();
}
public void getAnimal(){//dosomething}
public void packageAnimal(){//dosomething};
public void giveAnimal(){//dosomething};
}
可是这又有一个问题:子类需要更改模板方法中的两个或三个方法,那应该怎么办呢?
在这里先引出一个概念:方法钩子(Method Hook
)
方法钩子可以被理解为在一个超类中默认的方法实现,即子类继承后可自行选择是否去更改它。
所以,我们的动物商店超类可以改写为:
/**
* @Auther: ARong
* @Date: 2018/11/30 17:48
* @Description: 动物商店超类
*/
public abstract class AnimalShop {
//获取动物的模板方法
public void getAnimals(){
getAnimal();
packageAnimal();
giveAnimal();
}
//getAnimal是钩子方法,可供用户选择是否重写
public void getAnimal(){
System.out.println("获得动物");
}
//packageAnimal是打包动物抽象方法,由实现类重写
public abstract void packageAnimal();
//giveAnimal是打包动物抽象方法,由实现类重写
public abstract void giveAnimal();
}
这就是一个完备的模板方法模式超类了。接下来我们去继承它:
- DogShop
/**
* @Auther: ARong
* @Date: 2018/11/30 17:51
* @Description: 狗狗商店,实现动物商店超类,继承模板方法,重写抽象方法
*/
public class DogShop extends AnimalShop{
@Override
public void packageAnimal() {
System.out.println("将狗狗打包");
}
@Override
public void giveAnimal() {
System.out.println("将狗狗送出");
}
}
- CatShop
/**
* @Auther: ARong
* @Date: 2018/11/30 17:54
* @Description: 小猫商店,实现动物商店超类,继承模板方法,重写抽象方法
*/
public class CatShop extends AnimalShop{
@Override
public void getAnimal() {
//重写钩子方法,修改默认的代码
System.out.println("重写钩子方法,不要先获得小猫");
}
@Override
public void packageAnimal() {
System.out.println("将小猫打包");
}
@Override
public void giveAnimal() {
System.out.println("将小猫送出");
}
}
- TestTemplatePattern
/**
* @Auther: ARong
* @Date: 2018/11/30 17:56
* @Description: 模板方法测试
*/
public class TestTemplatePattern {
@Test
public void fun1(){
DogShop dogShop = new DogShop();
dogShop.getAnimals();
System.out.println("==================");
CatShop catShop = new CatShop();
catShop.getAnimals();
}
}
测试结果: