深入理解JavaScript系列(41):设计模式之模板方法详解


Posted in Javascript onMarch 04, 2015

介绍

模板方法(TemplateMethod)定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

模板方法是一种代码复用的基本技术,在类库中尤为重要,因为他们提取了类库中的公共行为。模板方法导致一种反向的控制结构,这种结构就是传说中的“好莱坞法则”,即“别找找我们,我们找你”,这指的是父类调用一个类的操作,而不是相反。具体体现是面向对象编程编程语言里的抽象类(以及其中的抽象方法),以及继承该抽象类(和抽象方法)的子类。

正文

举个例子,泡茶和泡咖啡有同样的步骤,比如烧开水(boilWater)、冲泡(brew)、倒在杯子里(pourOnCup),加小料(addCondiments)等等。但每种饮料冲泡的方法以及所加的小料不一样,所以我们可以利用模板方法实现这个主要步骤。

首先先来定义抽象步骤:

var CaffeineBeverage = function () {
};

CaffeineBeverage.prototype.prepareRecipe = function () {

    this.boilWater();

    this.brew();

    this.pourOnCup();

    if (this.customerWantsCondiments()) {

        // 如果可以想加小料,就加上

 this.addCondiments();

    }

};

CaffeineBeverage.prototype.boilWater = function () {

    console.log("将水烧开!");

};

CaffeineBeverage.prototype.pourOnCup = function () {

    console.log("将饮料到再杯子里!");

};

CaffeineBeverage.prototype.brew = function () {

    throw new Error("该方法必须重写!");

};

CaffeineBeverage.prototype.addCondiments = function () {

    throw new Error("该方法必须重写!");

};

// 默认加上小料

CaffeineBeverage.prototype.customerWantsCondiments = function () {

    return true;

};

该函数在原型上扩展了所有的基础步骤,以及主要步骤,冲泡和加小料步骤没有实现,供具体饮料所对应的函数来实现,另外是否加小料(customerWantsCondiments )默认返回true,子函数重写的时候可以重写该值。

下面两个函数分别是冲咖啡和冲茶所对应的函数:

// 冲咖啡

var Coffee = function () {

    CaffeineBeverage.apply(this);

};

Coffee.prototype = new CaffeineBeverage();

Coffee.prototype.brew = function () {

    console.log("从咖啡机想咖啡倒进去!");

};

Coffee.prototype.addCondiments = function () {

    console.log("添加糖和牛奶");

};

Coffee.prototype.customerWantsCondiments = function () {

    return confirm("你想添加糖和牛奶吗?");

};
//冲茶叶

var Tea = function () {

    CaffeineBeverage.apply(this);

};

Tea.prototype = new CaffeineBeverage();

Tea.prototype.brew = function () {

    console.log("泡茶叶!");

};

Tea.prototype.addCondiments = function () {

    console.log("添加柠檬!");

};

Tea.prototype.customerWantsCondiments = function () {

    return confirm("你想添加柠檬嘛?");

};

另外使用confirm,可以让用户自己选择加不加小料,很不错,不是嘛?

总结

模板方法应用于下列情况:

1.一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现
2.各子类中公共的行为应被提取出来并集中到一个公共父类中的避免代码重复,不同之处分离为新的操作,最后,用一个钓鱼这些新操作的模板方法来替换这些不同的代码
3.控制子类扩展,模板方法只在特定点调用“hook”操作,这样就允许在这些点进行扩展

和策略模式不同,模板方法使用继承来改变算法的一部分,而策略模式使用委托来改变整个算法。

Javascript 相关文章推荐
js中数组Array的一些常用方法总结
Aug 12 Javascript
基于JavaScript实现快速转换文本语言(繁体中文和简体中文)
Mar 07 Javascript
学习Bootstrap滚动监听 附调用方法
Jul 02 Javascript
Angular 4 依赖注入学习教程之FactoryProvider的使用(四)
Jun 04 Javascript
Vue框架中正确引入JS库的方法介绍
Jul 30 Javascript
vue.js,ajax渲染页面的实例
Feb 11 Javascript
vue.js中created方法作用
Mar 30 Javascript
inquirer.js一个用户与命令行交互的工具详解
May 18 Javascript
JS中数据结构与算法---排序算法(Sort Algorithm)实例详解
Jun 17 Javascript
Vue 实现登录界面验证码功能
Jan 03 Javascript
使用 Opentype.js 生成字体子集的实例代码详解
May 25 Javascript
纯JS开发baguetteBox.js响应式画廊插件
Jun 28 Javascript
深入理解JavaScript系列(40):设计模式之组合模式详解
Mar 04 #Javascript
百度地图自定义控件分享
Mar 04 #Javascript
jQuery实现仿淘宝带有指示条的图片转动切换效果完整实例
Mar 04 #Javascript
深入理解JavaScript系列(39):设计模式之适配器模式详解
Mar 04 #Javascript
深入理解JavaScript系列(38):设计模式之职责链模式详解
Mar 04 #Javascript
教你如何使用firebug调试功能了解javascript闭包和this
Mar 04 #Javascript
深入理解JavaScript系列(37):设计模式之享元模式详解
Mar 04 #Javascript
You might like
下载文件的点击数回填
2006/10/09 PHP
php实现获取及设置用户访问页面语言类
2014/09/24 PHP
基于php实现随机合并数组并排序(原排序)
2015/11/26 PHP
浅谈PHP拦截器之__set()与__get()的理解与使用方法
2016/10/18 PHP
几个javascript操作word的参考代码
2009/10/26 Javascript
文本框根据输入内容自适应高度的代码
2011/10/24 Javascript
js二维数组排序的简单示例代码
2014/01/24 Javascript
jQuery操作元素css样式的三种方法
2014/06/04 Javascript
jQuery将所有被选中的checkbox某个属性值连接成字符串的方法
2015/01/24 Javascript
JS实现两表格里数据来回转移的方法
2015/05/28 Javascript
PHP结合jQuery实现的评论顶、踩功能
2015/07/22 Javascript
jquery可定制的在线UEditor编辑器
2015/11/17 Javascript
js仿QQ中对联系人向左滑动、滑出删除按钮的操作
2016/04/07 Javascript
微信小程序 loading 详解及实例代码
2016/11/09 Javascript
jQuery表单验证之密码确认
2017/05/22 jQuery
js+html5实现复制文字按钮
2017/07/15 Javascript
JS获取input[file]的值并显示在页面的实现方法
2018/03/09 Javascript
基于JavaScript canvas绘制贝塞尔曲线
2018/12/25 Javascript
利用百度echarts实现图表功能简单入门示例【附源码下载】
2019/06/10 Javascript
新手快速入门JavaScript装饰者模式与AOP
2019/06/24 Javascript
vue-router跳转时打开新页面的两种方法
2019/07/29 Javascript
vue data对象重新赋值无效(未更改)的解决方式
2020/07/24 Javascript
js异步接口并发数量控制的方法示例
2020/11/22 Javascript
[05:03]2018DOTA2亚洲邀请赛主赛事首日回顾
2018/04/04 DOTA
python实现清屏的方法
2015/04/30 Python
使用Python3 编写简单信用卡管理程序
2016/12/21 Python
Django自定义分页效果
2017/06/27 Python
pygame游戏之旅 调用按钮实现游戏开始功能
2018/11/21 Python
在Python中获取操作系统的进程信息
2019/08/27 Python
Django接收照片储存文件的实例代码
2020/03/07 Python
Python自定义聚合函数merge与transform区别详解
2020/05/26 Python
浅谈PyTorch中in-place operation的含义
2020/06/27 Python
Tensorflow使用Anaconda、pycharm安装记录
2020/07/29 Python
捷克体育用品购物网站:D-sport
2017/12/28 全球购物
职专应届生求职信
2013/11/16 职场文书
《宋庆龄故居的樟树》教学反思
2014/04/07 职场文书