博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HeadFirst设计模式篇七:模板方法模式
阅读量:7192 次
发布时间:2019-06-29

本文共 1872 字,大约阅读时间需要 6 分钟。

hot3.png

问题引入:

  • 咖啡冲泡过程:

1、把水煮沸;

2、用沸水冲泡咖啡;

3、倒进杯子;

4、加咖啡和牛奶;

  • 茶冲泡过程:

1、把水煮沸;

2、用沸水浸泡茶叶;

3、倒进杯子;

4、加柠檬;

如果根据茶和咖啡各提供一个类然后提供冲泡的方法,会发现这两个类有很多重复的代码,而这个重复是体现在步骤1和3上。

解决方案:

抽取一个抽象父类,抽离出两个类一样的方法:冲泡和倒进杯子。不同的方法由具体子类实现。

public abstract class CaffeineBeverage {    final void prepareRecipe() {        //1、把水煮沸        boilWater();        //2、用沸水冲泡咖啡/或者是茶        brew();        //3、倒入杯中        pourInCup();        //4、加配料        addCondiments();    }    private void boilWater() {        //具体实现    }    protected abstract void brew();    private void pourInCup() {        //具体实现    }    protected abstract void addCondiments();}

模板方法模式定义:

在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

模板就是一个方法。更具体的说,这个方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。这可以确保算法的结构保持不变,同时由子类提供部分实现。

对模板方法进行挂钩

钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定。

public abstract class CaffeineBeverageWithHook {    final void prepareRecipe() {        //1、把水煮沸        boilWater();        //2、用沸水冲泡咖啡/或者是茶        brew();        //3、倒入杯中        pourInCup();        //是否加配料可以由子类决定        if(customerWantsCondiments()) {            //4、加配料            addCondiments();        }    }    /**     * 子类可以决定是否覆盖这个方法,子类可以选择不覆盖,不覆盖就默认加配料。     * @return     */    private boolean customerWantsCondiments() {        return true;    }    private void boilWater() {        //具体实现    }    protected abstract void brew();    private void pourInCup() {        //具体实现    }    protected abstract void addCondiments();}

当创建一个模板方法时,什么时候使用抽象方法,什么时候使用钩子?

当你的子类必须提供算法某个方法或者步骤的实现时,就是用抽象方法。如果算法的这个部分是可选的,就用钩子。

好莱坞原则:

别调用我们,我们会调用你。

低层组件参与计算,但高层组件控制何时以及如何让低层组件参与,低层组件绝对不可以调用高层组件。

工厂方法、策略模式、模板方法的比较:

工厂方法是模板方法的一种特殊版本,工厂方法是讲bean的实例化延迟到子类。而模板方法是将算法的步骤延迟到子类,都是用的是继承,但是目的不一样,我们可以称工厂方法是模板方法的特殊版本。

策略模式和模板方法模式都封装算法,但一个利用的是组合,一个利用的是继承,类似于策略模式中提到的jdk的comparable接口,应该归为模板方法,因为它体现的是继承。

转载于:https://my.oschina.net/silence88/blog/1036476

你可能感兴趣的文章
餐厅定位:编写一个程序,访问用户有多少人用餐。如果超过8个,就打印一条消息指出没有空桌,否则指出有空桌。...
查看>>
partition-list
查看>>
4.2. 入门案例
查看>>
Laravel资源理由器跟隐式控制的对比及是怎样的吧?- Route::resource vs Route::controller...
查看>>
mysql数据库分区功能及实例详解
查看>>
点击 小眼睛,和 i,
查看>>
OVN 问题小记
查看>>
mysql
查看>>
从hive将数据导出到mysql(转)
查看>>
写给来到这里的每一位
查看>>
dialog 中装listview并让每一个item分隔悬空,并具有radiobutton的效果
查看>>
ASP.NET中插入FLASH代码
查看>>
通过jquery 获取文本框的聚焦和失焦方法
查看>>
7 JavaScript Basics Many Developers Aren't Using (Properly)【转】
查看>>
Eclipse之JSP页面的使用
查看>>
Python入门篇-函数、参数及参数解构
查看>>
Android上获取本机安装的应用程序
查看>>
Android 手势识别
查看>>
[SVN(ubuntu)] ubuntu使用svn
查看>>
充电-ios(未完更新中...
查看>>