深入理解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 相关文章推荐
解析DHTML,JavaScript,DOM,BOM以及WEB标准的描述
Jun 19 Javascript
JS实现控制表格只显示行边框或者只显示列边框的方法
Mar 31 Javascript
jquery中实现时间戳与日期相互转换
Apr 12 Javascript
seajs学习之模块的依赖加载及模块API的导出
Oct 20 Javascript
Angularjs 与 bower安装和使用详解
May 11 Javascript
JS实现发送短信验证后按钮倒计时功能(防止刷新倒计时失效)
Jul 07 Javascript
快速解决vue在ios端下点击响应延时的问题
Aug 27 Javascript
浅谈关于JS下大批量异步任务按顺序执行解决方案一点思考
Jan 08 Javascript
小程序实现上下移动切换位置
Sep 23 Javascript
vue 使用 vue-pdf 实现pdf在线预览的示例代码
Apr 26 Javascript
Node.js API详解之 tty功能与用法实例分析
Apr 27 Javascript
Node.js API详解之 repl模块用法实例分析
May 25 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
Search Engine Friendly的URL设计
2006/10/09 PHP
Ajax+PHP 边学边练 之二 实例
2009/11/24 PHP
PHP爬虫之百万级别知乎用户数据爬取与分析
2016/01/22 PHP
PHP批量删除jQuery操作
2017/07/23 PHP
判断输入是否为空,获得输入类型的JS代码
2013/10/30 Javascript
jquery ajax 简单范例(界面+后台)
2013/11/19 Javascript
js实现背景图片感应鼠标变化的方法
2015/02/28 Javascript
JavaScript前补零操作实例
2015/03/11 Javascript
jQuery找出网页上最高元素的方法
2015/03/20 Javascript
javascript实现验证IP地址等相关信息代码
2015/05/10 Javascript
javascript自定义右键弹出菜单实现方法
2015/05/25 Javascript
js实现文字在按钮上滚动的方法
2015/08/20 Javascript
javascript判断图片是否加载完成的方法推荐
2016/05/13 Javascript
JS原型与原型链的深入理解
2017/02/15 Javascript
js数字舍入误差以及解决方法(必看篇)
2017/02/28 Javascript
javascript中replace使用方法总结
2017/03/01 Javascript
Bootstrap 网格系统布局详解
2017/03/19 Javascript
jQuery中clone()函数实现表单中增加和减少输入项
2017/05/13 jQuery
原生JS+CSS实现炫酷重力模拟弹跳系统的登录页面
2017/11/01 Javascript
js实现微信/QQ直接跳转到支付宝APP打开口令领红包功能
2018/01/09 Javascript
使用webpack/gulp构建TypeScript项目的方法示例
2019/12/18 Javascript
vue组件创建的三种方式小结
2020/02/03 Javascript
解决vue axios跨域 Request Method: OPTIONS问题(预检请求)
2020/08/14 Javascript
多线程爬虫批量下载pcgame图片url 保存为xml的实现代码
2013/01/17 Python
在Python中操作字符串之startswith()方法的使用
2015/05/20 Python
python 实现简单的FTP程序
2019/12/27 Python
Python趣味实例,实现一个简单的抽奖刮刮卡
2020/07/18 Python
Python SQLAlchemy库的使用方法
2020/10/13 Python
KIKO比利时官网:意大利彩妆品牌
2017/07/23 全球购物
英国玛莎百货澳大利亚:Marks & Spencer Australia
2019/08/30 全球购物
美丽的珠宝配饰:SmallThings
2019/09/04 全球购物
外贸销售员求职的自我评价
2013/11/23 职场文书
感情真挚的毕业生求职信
2014/07/19 职场文书
党的群众路线教育实践活动对照检查材料(个人)
2014/09/24 职场文书
Win11怎么进入安全模式?Windows 11进入安全模式的方法
2021/11/21 数码科技
Vue3如何理解ref toRef和toRefs的区别
2022/02/18 Vue.js