《javascript设计模式与开发实践》阅读笔记(11)—— 模板方法模式
来源:互联网 发布:mysql left join 编辑:程序博客网 时间:2024/05/18 01:49
模板方法模式:
由两部分结构组成,第一部分是抽象父类,第二部分是具体的实现子类。通常在抽象父类中封装了子类的算法框架,包括实现一些公共方法以及封装子类中所有方法的执行顺序。子类通过继承这个抽象类,也继承了整个算法结构,并且可以选择重写父类的方法。
泡咖啡和泡茶的例子
1 var Coffee = function(){}; //作为构造函数 2 Coffee.prototype.boilWater = function(){ 3 console.log( '把水煮沸' ); 4 }; 5 Coffee.prototype.brewCoffeeGriends = function(){ 6 console.log( '用沸水冲泡咖啡' ); 7 }; 8 Coffee.prototype.pourInCup = function(){ 9 console.log( '把咖啡倒进杯子' );10 };11 Coffee.prototype.addSugarAndMilk = function(){12 console.log( '加糖和牛奶' );13 };14 15 Coffee.prototype.init = function(){16 this.boilWater(); //煮水17 this.brewCoffeeGriends(); //泡咖啡18 this.pourInCup(); //倒进杯子19 this.addSugarAndMilk(); //加糖和牛奶20 };21 22 var coffee = new Coffee(); //实例一个“咖啡”对象23 coffee.init(); //调用24 25 26 var Tea = function(){}; //作为构造函数27 Tea.prototype.boilWater = function(){28 console.log( '把水煮沸' );29 };30 Tea.prototype.steepTeaBag = function(){31 console.log( '用沸水浸泡茶叶' );32 };33 Tea.prototype.pourInCup = function(){34 console.log( '把茶水倒进杯子' );35 };36 Tea.prototype.addLemon = function(){37 console.log( '加柠檬' );38 };39 40 Tea.prototype.init = function(){41 this.boilWater(); //煮水42 this.steepTeaBag(); //泡茶43 this.pourInCup(); //倒进杯子44 this.addLemon(); //加柠檬45 };46 47 var tea = new Tea(); //实例一个“茶”对象48 tea.init(); //调用
观察两段代码,发现其实他们是大同小异的,那我们完全可以把公共的部分抽象出来,作为一个抽象的父类模板
1 var drink=function(){} //作为抽象的构造类 2 drink.prototype.boilWater=function(){ 3 console.log( '把水煮沸' ); 4 } 5 drink.prototype.brew=function(){}; //空方法,用来给模板套用 6 drink.prototype.pourInCup = function(){}; // 同上 7 drink.prototype.addCondiments = function(){}; // 同上 8 9 drink.prototype.init = function(){ //模板在这里,重复的事情放在模板里10 this.boilWater();11 this.brew();12 this.pourInCup();13 this.addCondiments();14 };
然后就是具体的咖啡类和茶类
1 /**创建咖啡类**/ 2 var Coffee = function(){}; //这是一个具体的类,作为构造函数存在 3 Coffee.prototype = new drink(); //把构造函数的prototype指向抽象类的实例 4 5 Coffee.prototype.brew = function(){ 6 console.log( '用沸水冲泡咖啡' ); 7 }; 8 Coffee.prototype.pourInCup = function(){ 9 console.log( '把咖啡倒进杯子' );10 };11 Coffee.prototype.addCondiments = function(){12 console.log( '加糖和牛奶' );13 };14 15 var coffee = new Coffee(); //新建咖啡实例16 coffee.init(); //调用模板17 /*结果*/18 //把水煮沸19 //用沸水冲泡咖啡20 //把咖啡倒进杯子21 //加糖和牛奶
1 /**创建茶类**/ 2 var Tea = function(){}; //具体的类,作为构造函数 3 Tea.prototype = new drink(); //把构造函数的prototype指向抽象类的实例 4 5 Tea.prototype.brew = function(){ 6 console.log( '用沸水浸泡茶叶' ); 7 }; 8 Tea.prototype.pourInCup = function(){ 9 console.log( '把茶倒进杯子' );10 };11 Tea.prototype.addCondiments = function(){12 console.log( '加柠檬' );13 };14 15 var tea = new Tea(); //新建茶实例16 tea.init(); //调用模板17 /*结果*/18 //把水煮沸19 //用沸水浸泡茶叶20 //把茶倒进杯子21 //加柠檬
使用es6的话,代码可以简洁不少
1 class drink{ //抽象模板父类 2 boilWater(){ 3 console.log("把水煮沸"); 4 }; 5 brew(){}; 6 pourInCup(){}; 7 addCondiments(){}; 8 9 init(){10 this.boilWater();11 this.brew();12 this.pourInCup();13 this.addCondiments();14 }15 }16 17 class Coffee extends drink{ //具体的类,内部重写相应方法18 brew(){19 console.log("用沸水冲泡咖啡");20 }21 pourInCup(){22 console.log( '把咖啡倒进杯子' );23 }24 addCondiments(){25 console.log( '加糖和牛奶' );26 }27 }28 29 var coffee=new Coffee(); //实例30 coffee.init(); //把水煮沸31 //用沸水冲泡咖啡32 //把咖啡倒进杯子33 //加糖和牛奶
js实现模板模式的一些问题
我们在抽象父类中提供了模板,在具体的类中重写相应的方法,但是这个过程全靠程序员的自觉和记忆,语言层面并没有提供任何检查,如果我们忘了重写相应的方法,js也不会报错。
一种解决方案是用鸭子类型来模拟接口检查,缺点就是会带来很多不必要的复杂性,增加很多和业务无关的代码。
另一种解决方案是抽象父类中的相应抽象方法里都抛出错误,如果子类没有重写相应方法,运行时就会报错,如下:
1 drink.prototype.brew=function(){2 throw new Error( '子类必须重写brew 方法' );3 };
钩子方法
可以增加自由度,有的子类并不适合把模板方法全部运行,钩子方法可以让子类自行决定是否执行对应的模板方法。
1 drink.prototype.add=function(){ //钩子方法,子类中可以改写,模板方法中会进行判断 2 return true; //默认为true,用于判断 3 } 4 drink.prototype.init = function(){ //模板方法 5 this.boilWater(); 6 this.brew(); 7 this.pourInCup(); 8 if( this.add() ){ //如果挂钩返回true,则需要调料 9 this.addCondiments();10 }11 };
0 0
- 《javascript设计模式与开发实践》阅读笔记(11)—— 模板方法模式
- 《javascript设计模式与开发实践》阅读笔记(11)—— 模板方法模式
- 《javascript设计模式与开发实践》阅读笔记(11)—— 模板方法模式
- 《javascript设计模式与开发实践》阅读笔记(11)—— 模板方法模式
- 【学习笔记javascript设计模式与开发实践(模板方法模式)----11】
- 《javascript设计模式与开发实践》阅读笔记(10)—— 组合模式
- 《javascript设计模式与开发实践》阅读笔记(12)—— 享元模式
- 《javascript设计模式与开发实践》阅读笔记(14)—— 中介者模式
- 《javascript设计模式与开发实践》阅读笔记(12)—— 享元模式
- 《javascript设计模式与开发实践》阅读笔记(10)—— 组合模式
- 《javascript设计模式与开发实践》阅读笔记(12)—— 享元模式
- 《javascript设计模式与开发实践》阅读笔记(10)—— 组合模式
- 《javascript设计模式与开发实践》阅读笔记(14)—— 中介者模式
- 《javascript设计模式与开发实践》阅读笔记(一)
- 《javascript设计模式与开发实践》阅读笔记(二)
- 《javascript设计模式与开发实践》阅读笔记(三)
- 《javascript设计模式与开发实践》阅读笔记(四)
- 《javascript设计模式与开发实践》阅读笔记(五)——高阶函数
- 501. Find Mode in Binary Search Tree
- Java 从JavaAPI学习 java.util.Random
- androidStudio gralde zip version 问题
- 手机IMEI串码获取
- (8). 使用JPA保存数据【从零开始学Spring Boot】
- 《javascript设计模式与开发实践》阅读笔记(11)—— 模板方法模式
- UE4-蓝图基础:节点介绍
- H3 BPM如何批量导入用户和组织?
- www读取本地图片做微缩图
- Android基础-day01(快速入门)
- CTK框架介绍
- jQuery五角星评分
- 默认选中TreeView某个节点的方法
- srs之与nginx-rtmp性能对比