模板方法模式
假如我们有一些对象,各个对象之间有一些相同的行为,也有一些不同的行为,这时,我们就可以用模板方法模式来把相同的部分上移到它们的共同原型中(父类),而将不同的部分留给自己各自重新实现。
模板方法:在这些平行对象的共同原型中定义的一个方法,它封装了子类的算法框架,它作为一个算法的模板,指导子类以何种顺序去执行哪些方法。
模板方法常常被架构师用于搭建项目的框架,架构师定好了框架的骨架,程序员们继承框架的结构后,负责往里面填空。
模板方法模式中,常常用到一个钩子方法:在父类中的容易变化的方法上放置钩子,模板方法依据钩子方法的返回值来决定是否执行容易变化的方法。
模板方法模式是一种基于继承的设计模式,但在JavaScript中也可以通过高阶函数来实现。
基于继承的模板方法模式:
//模板方法模式
//泡茶和冲咖啡,有相似的方法,也有不同的方法
//相似的方法在父类中实现,不同的方法在子类中各自重写
var Beverage = function () {};
Beverage.prototype.boilWater = function () {
console.log('把水煮沸');
};
Beverage.prototype.pourMaterial = function (material) {
console.log('把'+material+'倒进杯子');
};
Beverage.prototype.pourInCup = function () {
console.log('把沸水倒进杯子');
};
Beverage.prototype.addCondiments = function () {
throw new Error('子类必须自行实现该方法');
};
//钩子方法,是否需要加配料
Beverage.prototype.isWantCondiments = function () {
return true; //默认为true,子类自行实现来改变返回值
};
//模板方法,规定了各个方法的执行顺序
Beverage.prototype.init = function (material) {
this.boilWater();
this.pourMaterial(material);
this.pourInCup();
if(this.isWantCondiments()){ //根据钩子方法的返回值决定是否执行
this.addCondiments();
}
};
//====子类
var Coffee = function () {};
Coffee.prototype = new Beverage(coffee);
Coffee.prototype.addCondiments = function () {
console.log('加糖');
};
Coffee.prototype.isWantCondiments = function () {
return window.confirm('请问需要加糖吗?');
};
//调用
var coffee = '咖啡粉';
var coffee1 = new Coffee();
coffee1.init(coffee);
通过高阶函数来实现:
var Beverage1 = function (obj,material) {
var boilWater = function(){
console.log('把水煮沸');
};
var pourMaterial = function(material){
console.log('把'+material+'倒进杯子');
};
var pourInCup = function () {
console.log('把沸水倒进杯子');
};
var addCondiments = obj.addCondiments||function () {
throw new Error('子类必须自行实现该方法');
};
var isWantCondiments = obj.isWantCondiments||function () {
return true; //默认为true,子类自行实现来改变返回值
};
var F = function(){};
F.prototype.init = function(){
boilWater();
pourMaterial(material);
pourInCup();
if(isWantCondiments()){ //根据钩子方法的返回值决定是否执行
addCondiments();
}
};
return F;
};
//定义子类
var Coffee1 = Beverage1({
addCondiments: function(){
console.log('加糖');
},
isWantCondiments: function () {
return window.confirm('请问需要加糖吗?');
}
},'咖啡粉');
var Tea1 = Beverage1({
addCondiments: function(){
console.log('加柠檬');
},
isWantCondiments: function () {
return window.confirm('请问需要加柠檬吗?');
}
},'茶叶');
var aCupOfCoffee = new Coffee1();
aCupOfCoffee.init();
//把水煮沸
//把咖啡粉倒进杯子
//把沸水倒进杯子
//加糖(点确定)
var aCupOfTea = new Tea1();
aCupOfTea.init();
//把水煮沸
//把茶叶倒进杯子
//把沸水倒进杯子
//加柠檬(点确定)
参考文献: 《JavaScript模式》 《JavaScript设计模式与开发实践》
轻松掌握:JavaScript模板方法模式的更多相关文章
-
javascript模板方法模式
一:什么是模板方法模式: 模板方法模式由二部分组成,第一部分是抽象父类,第二部分是具体实现的子类,一般的情况下是抽象父类封装了子类的算法框架,包括实现一些公共方法及封装子类中所有方法的执行顺序,子类可 ...
-
《JavaScript设计模式与开发实践》读书笔记之模板方法模式
1. 模板方法模式 1.1 面向对象方式实现模板方法模式 以泡茶和泡咖啡为例,可以整理为下面四步 把水煮沸 用沸水冲泡饮料 把饮料倒进杯子 加调料 首先创建一个抽象父类来表示泡一杯饮料 var Bev ...
-
再起航,我的学习笔记之JavaScript设计模式17(模板方法模式)
模板方法模式 由模板方法模式开始我们正式告别结构型设计模式,开始行为型设计模式的学习分享 行为型设计模式用于不同对象之间职责划分或算法抽象,行为型设计模式不仅仅涉及类和对象,还涉及类或对象之间的交流模 ...
-
javascript设计模式——模板方法模式
前面的话 在javascript开发中用到继承的场景其实并不是很多,很多时候喜欢用mix-in的方式给对象扩展属性.但这不代表继承在javascript里没有用武之地,虽然没有真正的类和继承机制,但可 ...
-
JavaScript设计模式-----模板方法模式
模板方法模式是一种只需要使用继承就可以实现的非常简单点的模式. 模板方法模式有两部分组成,第一部分是抽象父类,第二部分是具体的实现子类.通常在抽象父类中封装了子类的算法框架,包括实现 一些公共方法以及 ...
-
[设计模式] javascript 之 模板方法模式
模板方法模式说明 定义:定义方法操作的骨架,把一些具体实现延伸到子类中去,使用得具体实现不会影响到骨架的行为步骤! 说明:模式方法模式是一个继承跟复用的典型模式,该模式定义了一个抽象类,Abstrac ...
-
javascript设计模式与开发实践阅读笔记(11)—— 模板方法模式
模板方法模式: 由两部分结构组成,第一部分是抽象父类,第二部分是具体的实现子类.通常在抽象父类中封装了子类的算法框架,包括实现一些公共方法以及封装子类中所有方法的执行顺序.子类通过继承这个抽象类,也继 ...
-
javascript设计模式(张容铭)学习笔记 - 照猫画虎-模板方法模式
模板方法模式(Template Method):父类中定义一组操作算法骨架,而降一些实现步骤延迟到子类中,使得子类可以不改变父类的算法结构的同时可重新定义算法中某些实现步骤. 项目经理体验了各个页面的 ...
-
PHP设计模式之模板方法模式
模板方法模式,也是我们经常会在不经意间有会用到的模式之一.这个模式是对继承的最好诠释.当子类中有重复的动作时,将他们提取出来,放在父类中进行统一的处理,这就是模板方法模式的最简单通俗的解释.就像我们平 ...
随机推荐
-
mysql 存储引擎
什么是MySql数据库 通常意义上,数据库也就是数据的集合,具体到计算机上数据库可以是存储器上一些文件的集合或者一些内存数据的集合. 我们通常说的MySql数据库,sql server数据库等等 ...
-
CSS的一些简单概念
行内元素与块级元素 在标准文档流里面,块级元素具有以下特点: ①总是在新行上开始,占据一整行:②高度,行高以及外边距和内边距都可控制:③宽带始终是与浏览器宽度一样,与内容无关:④它可以容纳内联元素和其 ...
-
Math.Round函数详解
有不少人误将Math.Round函数当作四舍五入函数在处理, 结果往往不正确, 实际上Math.Round采用的是国际通行的是 Banker 舍入法. Banker's rounding(银行家舍入) ...
-
List Comprehensions
看Python高级编程时有几个东西要记一记,方便以后查询 以下代码基本全摘自Python高级编程 取0~9之间的偶数,类C语言写法: 使用list comprehensions可以极大程度上简化语法: ...
-
Ext Grid 加载超时设置timeout: 180000
var insideGridStore = Ext.create('Ext.data.Store', { model: 'CarComponents',//这个地方CarComponents不是一个对 ...
-
MySQL的MyISAM和InnoDB对比及优化(转)
MyISAM和InnoDB是在使用MySQL最常用的两个表类型,各有优缺点,视具体应用而定.基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持.MyISAM类型的表强调的是 ...
-
不用SWIG,Go使用C++代码的方式
将C++代码用C作一次封装,就可以让Go调用了. 这是一个C++头文件: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #ifndef CGO_CPPGO_C ...
-
Python打包EXE神器 pyinstaller
最近由于项目需要,以前的python文件需要编辑为EXE供前端客户使用. 由于最早接触的是distutils,所以一开始准备使用distutils和py2exe搭配来进行python的exe化,也就是 ...
-
linux下网卡相关查看设置
查整机硬件信息命令dmesg 查看网卡设备相关dmesg | grep eth 查看网卡eth0信息dmesg | grep eth0 使用ethtool命令查看指定网卡信息ethtool eth0 ...
-
Oracle 数据库监听配置和服务
-- 补充说明 如果要远程连接192.168.10.44上的oracle,那么192.168.10.44服务器必须启动TNSListener.(配置文件 listener.ora) PLSQL Dev ...