模板方法设计模式
一、模板方法设计模式
1、介绍
(1)模板方法设计模式(Template Method Pattern),也叫模板模式(Template Pattern)。在一个抽象类公开定义了执行它的方法模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
(2)模板方法设计模式就是定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤。
(3)模板方法设计模式属于行为型模式。
2、UML
抽象类A:类中实现了模板方法(template),定义了算法的骨架,具体子类需要去实现抽象方法a3
类A1和类A2:需要实现父类(A)抽象方法a3,用来完成算法特定步骤
3、注意事项和细节
-
基本思想事:算法只存在一个地方,也就是在父类中。容易修改,需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改
-
实现最大代码复用。父类的模板方法和已经实现的步骤会被子类继承而直接使用
-
即统一了算法,也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤实现。
-
不足之处:每一个不同的实现都需要一个子类,导致类的个数增加,使得系统更加庞大
-
一般模板方法都加上final关键字,防止子类重写模板方法
-
模板方法模式使用场景:当要完成某个过程,该过程要执行一系列步骤,这一系列步骤基本相同,但其个别步骤在是现实时可能不同,通常考虑用模板方法模式来处理
二、模板方法设计模式案例
1、介绍
使用模板方法设计模式制作不同配料的豆浆
2、UML
3、代码
/**
* @description: 豆浆
* @author: dashu
* @create: 13:19
*/
public abstract class SoyaMilk {
/**
* 模板方法make,final声明,禁止子类覆盖
*/
public final void make(){
select();
addCondiments();
soak();
beat();
}
/**
* 选材料
*/
public void select(){
System.out.println("第一步:选择好的新鲜黄豆");
}
/**
* 添加配料,抽象方法,由子类具体实现
*/
public abstract void addCondiments();
/**
* 侵泡
*/
public void soak(){
System.out.println("第三步:将黄豆和配料侵泡3小时");
}
/**
* 制作
*/
public void beat(){
System.out.println("第四步:将黄豆和配料放入豆浆机制作");
}
}
/**
* @description: 红豆豆浆
* @author: dashu
* @create: 13:24
*/
public class RedBeanSoyaMilk extends SoyaMilk{
/**
* 添加配料
*/
@Override
public void addCondiments() {
System.out.println("第二步:添加红豆");
}
}
/**
* @description: 花生豆浆
* @author: dashu
* @create: 13:25
*/
public class PeanutSoyaMilk extends SoyaMilk{
/**
* 添加配料
*/
@Override
public void addCondiments() {
System.out.println("第二步:添加花生");
}
}
/**
* @description: 客户端
* @author: dashu
* @create: 13:18
*/
public class Client {
public static void main(String[] args) {
System.out.println("制作红豆豆浆:");
SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
redBeanSoyaMilk.make();
System.out.println("--------------------------");
System.out.println("制作花生豆浆:");
SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
peanutSoyaMilk.make();
}
}
三、模板方法设计模式案例(钩子方法)
1、介绍
在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为钩子
2、UML
3、代码
/**
* @description: 豆浆
* @author: dashu
* @create: 13:19
*/
public abstract class SoyaMilk {
/**
* 模板方法make,final声明,禁止子类覆盖
*/
public final void make(){
select();
if (customerWantCondiments()){
addCondiments();
}
soak();
beat();
}
/**
* 选材料
*/
public void select(){
System.out.println("第一步:选择好的新鲜黄豆");
}
/**
* 添加配料,抽象方法,由子类具体实现
*/
public abstract void addCondiments();
/**
* 侵泡
*/
public void soak(){
if (customerWantCondiments()){
System.out.println("第三步:将黄豆和配料侵泡3小时");
}else{
System.out.println("第二步:将黄豆侵泡3小时");
}
}
/**
* 制作
*/
public void beat(){
if (customerWantCondiments()){
System.out.println("第四步:将黄豆和配料放入豆浆机制作");
}else{
System.out.println("第三步:将黄豆放入豆浆机制作");
}
}
/**
* 是否添加配料,钩子方法
*
* @return
*/
public boolean customerWantCondiments(){
return false;
}
}
/**
* @description: 红豆豆浆
* @author: dashu
* @create: 13:24
*/
public class RedBeanSoyaMilk extends SoyaMilk {
/**
* 添加配料
*/
@Override
public void addCondiments() {
System.out.println("第二步:添加红豆");
}
/**
* 是否添加配料
*
* @return
*/
@Override
public boolean customerWantCondiments() {
return true;
}
}
/**
* @description: 花生豆浆
* @author: dashu
* @create: 13:25
*/
public class PeanutSoyaMilk extends SoyaMilk {
/**
* 添加配料
*/
@Override
public void addCondiments() {
System.out.println("第二步:添加花生");
}
@Override
public boolean customerWantCondiments() {
return super.customerWantCondiments();
}
}
/**
* @description: 客户端
* @author: dashu
* @create: 13:18
*/
public class Client {
public static void main(String[] args) {
System.out.println("制作红豆豆浆:");
SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
redBeanSoyaMilk.make();
System.out.println("--------------------------");
System.out.println("制作花生豆浆:");
SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
peanutSoyaMilk.make();
}
}