深入理解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类的定义
Jun 28 Javascript
几种延迟加载JS代码的方法加快网页的访问速度
Oct 12 Javascript
jquery 实现返回顶部功能
Nov 17 Javascript
jQuery老黄历完整实现方法
Jan 16 Javascript
JS实现淡入淡出图片效果的方法分析
Dec 20 Javascript
AngularJS学习第二篇 AngularJS依赖注入
Feb 13 Javascript
JavaScript求一个数组中重复出现次数最多的元素及其下标位置示例
Jul 23 Javascript
Mint UI实现A-Z字母排序的城市选择列表
Dec 28 Javascript
jquery的$().each和$.each的区别
Jan 18 jQuery
微信小程序实现搜索历史功能
Mar 26 Javascript
浅谈React Native 传参的几种方式(小结)
May 21 Javascript
vue设置全局访问接口API地址操作
Aug 14 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
德生9700DX电路分析
2021/03/02 无线电
php中定义网站根目录的常用方法
2010/08/08 PHP
php中常用字符串处理代码片段整理
2011/11/07 PHP
php中限制ip段访问、禁止ip提交表单的代码分享
2014/08/22 PHP
php session的锁和并发
2016/01/22 PHP
详解PHP使用Redis存储session时的一个Warning定位
2017/07/05 PHP
不用AJAX和IFRAME,说说真正意义上的ASP+JS无刷新技术
2008/09/25 Javascript
jQuery 1.2.x 升? 1.3.x 注意事项
2009/05/06 Javascript
js动画效果制件让图片组成动画代码分享
2014/01/14 Javascript
js实现弹出窗口、页面变成灰色并不可操作的例子分享
2014/05/10 Javascript
Lua表达式和控制结构学习笔记
2014/12/15 Javascript
基于javascript实现最简单的选项卡切换效果
2016/05/16 Javascript
微信小程序中用WebStorm使用LESS
2017/03/08 Javascript
vue实现选项卡及选项卡切换效果
2018/04/24 Javascript
axios+Vue实现上传文件显示进度功能
2019/04/14 Javascript
javascript 使用sleep函数的常见方法详解
2020/04/26 Javascript
[00:35]2016完美“圣”典风云人物:冷冷宣传片
2016/12/08 DOTA
采用python实现简单QQ单用户机器人的方法
2014/07/03 Python
使用Python判断质数(素数)的简单方法讲解
2016/05/05 Python
Python 实现文件的全备份和差异备份详解
2016/12/27 Python
python清理子进程机制剖析
2017/11/23 Python
Python中常见的异常总结
2018/02/20 Python
Python中创建二维数组
2018/10/17 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
2019/05/10 Python
Python Pandas实现数据分组求平均值并填充nan的示例
2019/07/04 Python
Python 多线程共享变量的实现示例
2020/04/17 Python
Python QT组件库qtwidgets的使用
2020/11/02 Python
css3实现文字首尾衔接跑马灯的示例代码
2020/10/16 HTML / CSS
奶茶店创业计划书范文
2014/01/17 职场文书
班主任经验交流会主持词
2014/04/01 职场文书
学雷锋志愿者活动总结
2014/06/27 职场文书
委托书格式要求
2015/01/28 职场文书
2015医德医风个人工作总结
2015/04/02 职场文书
公司宣传语大全
2015/07/13 职场文书
女儿满月酒致辞
2015/07/29 职场文书
Nginx已编译的nginx-添加新模块
2021/04/01 Servers