设计模式-----模板方法模式
来源:互联网 发布:美蓝漫画无法连接网络 编辑:程序博客网 时间:2024/06/08 03:06
设计模式—–模板方法模式
个人博客,想要搭建个人博客的可以进来看看: http://www.ioqian.top/
策略模式,在一个方法中定义一个算法的骨架,而将一些具体的步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤
设计模式系列博客代码: https://github.com/liloqian/DesiginModeDemo
背景 , 我们的生活过程中,煮茶和咖啡的工作看起来不同,但是都可以分为下面4步,烧水,把茶或者咖啡放入水中,把咖啡或者水放到杯子中,加入调料,我们可以把公共的操作步骤提取出来放在抽象类中,不同的部分放在子类去实现
1.UML
- AbstractClass 抽象父类部分,背景中的烧水喝倒入杯子等固定的动作放在抽象父类实现
- ConcreteClass 具体实现类 , 茶还是咖啡,加糖还是柠檬让具体子类实现
最使用模板方法中,只需要调用具体实现类的模板方法就可以
2.代码
AbstractClass
/**抽象父类*/public abstract class CaffeineBeverage { /**模板方法,对外提供的接口*/ public final void prepareRecipe() { boilWater(); brew(); pourInCup(); addCondiments(); } //改变的部分让子类去实现 abstract void brew(); abstract void addCondiments(); //固定的部分直接实现,使用private关键字让外部无法调用 // final关键字是让子类重写改变这个方法 private final void boilWater() { System.out.println("boil the water"); } private final void pourInCup() { System.out.println("pour in cup"); }}
具体类
/**具体模板类,实现了tea特性的操作*/public class Tea extends CaffeineBeverage { @Override void brew() { System.out.println("brew the tea"); } @Override void addCondiments() { System.out.println("add lemon"); }}//和上面相同public class Coffee extends CaffeineBeverage { @Override void brew() { System.out.println("brew the coffee"); } @Override void addCondiments() { System.out.println("add sugar and milk"); }}
测试Main
public class Main { public static void main(String[] args) { //准备tea System.out.println("Prepare the tea ..."); CaffeineBeverage tea = new Tea(); tea.prepareRecipe(); //只要调用模板的方法,不关心怎么实现的 //准备coffee System.out.println("Prepare the coffee..."); CaffeineBeverage coffee = new Coffee(); coffee.prepareRecipe(); }}//结果Prepare the tea ...boil the waterbrew the teapour in cupadd lemonPrepare the coffee...boil the waterbrew the coffeepour in cupadd sugar and milkProcess finished with exit code 0
3.总结
- 模板抽象类是对外提供了唯一的算法,并且使用final关键字保护了这个算法,在以后算法的修改时,仅仅改这一处就可以了
- 模板抽象类实现了共同的操作,将代码复用最大化
- 模板方法提供了一个框架,让其他的具体实现者来实现细节
4.模板方法模式中的钩子
改进,使用钩子hook(),在上面的背景例子中,咖啡和茶的都可以抽象为4个步骤,但是当存在一种实例只有3中步骤,比如可乐就不需要烧水操作,我们应该怎样把他们统一到模板方法中,这个时候就可以使用钩子了
改变抽象类方法
/**抽象父类*/public abstract class CaffeineBeverage { /**模板方法,对外提供的接口*/ public final void prepareRecipe() { //通过一个方法判断是否需要烧水,直接实现中返回true,但是当可乐时可以重写 isNeedBoilWater()返回false if(isNeedBoilWater()){ boilWater(); } brew(); pourInCup(); addCondiments(); } //改变的部分让子类去实现 abstract void brew(); abstract void addCondiments(); //固定的部分直接实现,使用private关键字让外部无法调用 // final关键字是让子类重写改变这个方法 private final void boilWater() { System.out.println("boil the water"); } private final void pourInCup() { System.out.println("pour in cup"); } //-----changed-----不是final让子类可以改变 private boolean isNeedBoilWater(){ return true; }}
看了上面的代码,应该对钩子有了理解了,isNeedBoilWater()就是钩子方法;当我们创建一个模板方法时,如果子类必须实现的一个方法就是有抽象方法,如果这个方法时可选的就使用钩子
5.模板方法模式中的好莱坞原则
好莱坞原则 , 别调用我们,我们会调用你;高层组件调用底层组件,底层组件不要去调用高层组件
看起来很懵逼,不知道什么意思。结合我们的模板方法模式来理解一下,我们的抽象父类(高层组件)调用了具体实现类(底层组件)的方法,这里具体实现类实现了抽象方法,但是抽象具体类不可以调用抽象父类的方法
6.模板方法模式在JDK中的使用
我们都知道集合是我们常用的一个类,大部分集合是可以排序的,比如说ArrayList,可以对ArrayList中的成员进行排序,但是不是每种存储在ArrayList中的类都可以排序的,可以排序的类必须实现了Comparable接口(public int compareTo(T o);唯一的方法),我们在使用Double,Integer中直接可以排序是因为这些类继承了Comparable接口的,可以去看看源码,这就是一个模板方法模式的使用
/**继承了Comparable接口,Duck类可以使用sort方法*/public class Duck implements Comparable{ //在comparTo()中使用这个int类型排序 int weight; public Duck(int weight) { this.weight = weight; } @Override public int compareTo(Object o) { Duck oDuck = (Duck) o; if(this.weight > oDuck.weight){ return 1; }else if(this.weight == oDuck.weight){ return 0; }else { return -1; } } //重写了toString()后面的打印中使用 @Override public String toString() { return "my weight is " + this.weight; } //测试main public static void main(String[] args) { //new个ArrayList List<Duck> ducks = new ArrayList<>(); for(int i =0 ; i < 10 ;i++){ ducks.add(new Duck((int)(Math.random()*100))); } //未排序前打印集合信息 show(ducks); System.out.println("\n\n"); //排序 Collections.sort(ducks); //排序后再次打印 show(ducks); } //打印集合信息 private static void show(List<Duck> lists){ for (Duck duck : lists) { System.out.println(duck.toString()); } }}
- 设计模式:模板方法模式
- 设计模式 - 模板方法模式
- 设计模式:模板方法模式
- 设计模式 模板方法模式
- 设计模式--模板方法模式
- 设计模式-【模板方法模式】
- 设计模式: 模板方法模式
- 设计模式- 模板方法模式
- 设计模式 - 模板方法模式
- 设计模式 - 模板方法模式
- 设计模式-模板方法模式
- 设计模式-模板方法模式
- 设计模式---模板方法模式
- 设计模式-模板方法模式
- 设计模式--模板方法模式
- 设计模式-模板方法模式
- 设计模式------模板方法模式
- 设计模式----模板方法模式
- 笨方法学python 习题34(访问列表元素)习题35(作死小游戏)
- 页面验证码的显示与点击刷新问题
- 【LeetCode】165. Compare Version Numbers
- Java中的反射机制
- H5页面在iOS网页中的数字被识别为电话号码(数字颜色自动被改变成蓝色)?
- 设计模式-----模板方法模式
- javaboy第一章
- Android Studio无法查看SDK源码问题
- 尝试分解业务
- Python虚拟环境在离线断网环境下创建项目虚拟环境和安装依赖包
- Servlet笔记四
- 科大讯飞
- 数字金字塔(动态规划 输出路径)
- Android RecyclerView设置点击事件