java设计模式6-模版方法模式
问题引入
豆浆制作问题
编写制作豆浆的程序
1、制作豆浆流程:选材--》添加配料--》放到豆浆机打磨
2、通过添加不同的配料,可以制作不同口味的豆浆
3、选材、浸泡和放入豆浆机这几个步骤对于制作每种口味的豆浆都是一样的
模版方法模式
基本介绍
1、模版方法,又叫模版方法模式,在一个抽象类公开定义了指向它的方法的模版.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行
2、简单说,模版方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤.
3、这种类型的设计模式属于行为型模式
类图
1、AbstractClass抽象类,类中实现了模版方法,定义了算法骨架,具体子类需要去实现其他的抽象方法operation1,2,3
2、ConcreteClass实现抽象方法operation1,2,3,以完成算法中特定子类的步骤
模版方法解决豆浆制作问题
思路
代码
//抽象类,表示豆浆 public abstract class SoyaMilk { //模板方法, make , 模板方法可以做成final , 不让子类去覆盖. final void make() { select(); addCondiments(); soak(); beat(); } //选材料 void select() { System.out.println("第一步:选择好的新鲜黄豆 "); } //添加不同的配料, 抽象方法, 子类具体实现 abstract void addCondiments(); //浸泡 void soak() { System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 "); } void beat() { System.out.println("第四步:黄豆和配料放到豆浆机去打碎 "); } }
public class RedSoyaMilk extends SoyaMilk { @Override void addCondiments() { // TODO Auto-generated method stub System.out.println(" 加入上好的红豆 "); } }
public class PeanutSoyaMilk extends SoyaMilk { @Override void addCondiments() { // TODO Auto-generated method stub System.out.println(" 加入上好的花生 "); } }
public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //制作红豆豆浆 System.out.println("----制作红豆豆浆----"); SoyaMilk redBeanSoyaMilk = new RedSoyaMilk(); redBeanSoyaMilk.make(); System.out.println("----制作花生豆浆----"); SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk(); peanutSoyaMilk.make(); } }
模版方法模式的钩子方法
1、在模版方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,这样的方法就是钩子方法
2、还是用上面做豆浆的例子,比如,我们还希望做纯豆浆,不添加任何配料,请使用钩子函数对前面的模版方法进行改造
代码
//抽象类,表示豆浆 public abstract class SoyaMilk { //模板方法, make , 模板方法可以做成final , 不让子类去覆盖. final void make() { select(); if (customerWantCondiments()){ addCondiments(); } soak(); beat(); } //钩子方法,决定是否需要添加配料 public boolean customerWantCondiments() { return true; } //选材料 void select() { System.out.println("第一步:选择好的新鲜黄豆 "); } //添加不同的配料, 抽象方法, 子类具体实现 abstract void addCondiments(); //浸泡 void soak() { System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 "); } void beat() { System.out.println("第四步:黄豆和配料放到豆浆机去打碎 "); } }
public class PureSoyaMilk extends SoyaMilk { @Override void addCondiments() { // TODO Auto-generated method stub //空实现 } @Override //钩子方法,决定是否需要添加配料 public boolean customerWantCondiments() { return false; } }
模版方法在spring中的源码分析
1、SpringIOC容器初始化时运用到了模版方法模式
2、实现接口
注意事项和细节
1、基本思想:算法只存在于一个地方,也就是在父类中,容易修改.修改只需修改父类的模版方法,或者已经实现的步骤,子类就会继承这些修改
2、实现可最大化代码复用.父类的模版方法和已经实现的某些步骤会被子类继承而直接使用
3、父类的模版方法确保了算法结构的不变,同时由子类提供部分步骤的实现
4、该模式的缺点:每一个不同的实现都需要一个子类,导致类的个数增加,使得系统庞大
5、一般模版方法都加上final关键字,防止子类重写模版方法
使用场景
a) 当要完成在某个过程,该过程要执行一系列步骤,且步骤基本相同,但个别步骤在实现时会不同,通常考虑使用模版方法