深入理解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 相关文章推荐
跨浏览器开发经验总结(四) 怎么写入剪贴板
May 13 Javascript
JavaScript的document对象和window对象详解
Dec 30 Javascript
使用 JScript 创建 .exe 或 .dll 文件的方法
Jul 13 Javascript
自定义jQuery选项卡插件实例
Mar 27 Javascript
JavaScript 中的日期和时间及表示标准介绍
Aug 21 Javascript
jquery实现兼容浏览器的图片上传本地预览功能
Oct 14 Javascript
js二维数组定义和初始化的三种方法总结
Mar 03 Javascript
FF(火狐)浏览器无法执行window.close()解决方案
Nov 13 Javascript
使用javascript实现监控视频播放并打印日志
Jan 05 Javascript
Vue实现路由跳转和嵌套
Jun 20 Javascript
AngularJS对动态增加的DOM实现ng-keyup事件示例
Mar 12 Javascript
jQuery利用FormData上传文件实现批量上传
Dec 04 jQuery
深入理解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
IP攻击升级,程序改进以对付新的攻击
2010/11/23 PHP
php利用腾讯ip分享计划获取地理位置示例分享
2014/01/20 PHP
PHP实现多图片上传类实例
2014/07/26 PHP
ThinkPHP中自定义目录结构的设置方法
2014/08/15 PHP
PHP实现实时生成并下载超大数据量的EXCEL文件详解
2017/10/23 PHP
php实现姓名根据首字母排序的类与方法(实例代码)
2018/05/16 PHP
PHP+iframe模拟Ajax上传文件功能示例
2019/07/02 PHP
javascript 24小时弹出一次的代码(利用cookies)
2009/09/03 Javascript
js的写法基础分析
2011/01/17 Javascript
JavaScript中为元素加上name属性的方法
2011/05/09 Javascript
javaScript矢量图表库-gRaphael几行代码实现精美的条形图/饼图/点图/曲线图
2013/01/09 Javascript
将list转换为json失败的原因
2013/12/17 Javascript
js获取url中的参数且参数为中文时通过js解码
2014/03/19 Javascript
JavaScript节点及列表操作实例小结
2015/08/05 Javascript
Javascript仿新浪游戏频道鼠标悬停显示子菜单效果
2015/08/21 Javascript
基于JavaScript如何实现私有成员的语法特征及私有成员的实现方式
2015/10/28 Javascript
详解Javascript模板引擎mustache.js
2016/01/20 Javascript
mvc 、bootstrap 结合分布式图简单实现分页
2016/10/10 Javascript
微信小程序 合法域名校验出错详解及解决办法
2017/03/09 Javascript
基于react框架使用的一些细节要点的思考
2017/05/31 Javascript
iscroll实现下拉刷新功能
2017/07/18 Javascript
实现div内部滚动条滚动到底部和顶部的代码
2017/11/15 Javascript
Node.js事件的正确使用方法
2019/04/05 Javascript
js实现图片上传即时显示效果
2019/09/30 Javascript
小程序中的箭头函数的具体使用
2020/06/19 Javascript
JavaScript Image对象实现原理实例解析
2020/08/26 Javascript
vue深度监听(监听对象和数组的改变)与立即执行监听实例
2020/09/04 Javascript
[01:17:55]VGJ.T vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/20 DOTA
使用python实现ANN
2017/12/20 Python
应用OpenCV和Python进行SIFT算法的实现详解
2019/08/21 Python
Right-on官方网站:日本知名的休闲服装品牌
2019/07/12 全球购物
个人社会实践自我鉴定
2014/03/24 职场文书
2014年党员个人工作总结
2014/12/02 职场文书
结婚当天新郎保证书
2015/05/08 职场文书
golang 实现菜单树的生成方式
2021/04/28 Golang
梳理总结Python开发中需要摒弃的18个坏习惯
2022/01/22 Python