本文共 3537 字,大约阅读时间需要 11 分钟。
一、模板方法模式
js 中没有抽象类,模板方法就是父类的方法的执行,依赖于子类来完成,如果子类没有现实,那么就是一个空方法。
1、类java方式演示模板方法
var Root = function() { } // init 就是模板方法,它有些方法是调用了未声明(抽象类未实现)的方法。 Root.prototype.init = function() { this.opt1(); this.opt2(); this.opt3(); } Root.prototype.opt1 = function() { }
2、参数传入模板方法调用的未声明或实现的方法,并且如果参数不传入,那么会抛出异常。
var Root = function(param) { var opt1 = param.opt1 || function() { throw new Error( 'opt1 must not undifined ' ); } var opt2 = param.opt2 || function() { throw new Error( 'opt2 must not undifined ' ); } var fn = function() {} fn.prototype.init = function() { opt1(); opt2(); } return fn; }
二、监听器模式
监听器模式,主要有三个方法组成,listen:添加监听方法,trigger :触发监听方法,remove:移除监听。
var Event = (function() { var cache = {}, listen, trigger, remove, listen = function(key,fn) { if(!cache[key]) { cache[key] = []; } cache[key].push(fn); } trigger = function() { var key = Array.prototype.shift.call(arguments); fns = cache[key]; if(!fns || fns.length === 0) { return false; } for(var i=0, fn; fn=fns[i++];) { fn.apply(this, arguments); } } remove = function(key, fn) { var fns = cache[key]; if(fns) { if(!fn) { fns.length = 0; }else { for (var j = fns.length - 1; j >= 0; j--) { var _fn = fns[j]; if (_fn === fn) { fns.splice(j, 1); } } } } } return{ listen, trigger, remove }})();Event.listen('squareMeter88', function (price) { // 小红订阅消息 console.log('价格= ' + price); // 输出:'价格=2000000'});Event.trigger('squareMeter88', 2000000); // 售楼处发布消息
三、命令模式
1、js命令模式
// 有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么 ,这个时候,我们将请求的接收者包装成单个命令。
// 1、js命令模式 // 有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么 ,这个时候,我们将请求的接收者包装成单个命令。 // 1) 命令接收者 var Light = { on() { console.log('开'); }, off() { console.log('关'); } } // 2) 命令包装-开方法 function CommandOn(receiver) { this.receiver = receiver; } CommandOn.prototype.excute = function() { this.receiver.on(); } // 3) 命令包装-关方法 function CommandOff(receiver) { this.receiver = receiver; } CommandOff.prototype.excute = function() { this.receiver.off(); } // 4) 调用命令执行 var setCommand = function(command){ command.excute() }; var c1 = new CommandOn(Light); var c2 = new CommandOff(Light); setCommand(c1); setCommand(c2);
2、简化模式--由于js函数可以直接传参,我们可以不用包装成通用excute对象,即使用Light.on方式
setCommand = function(fn) { fn & fn(); } setCommand(Light.on); setCommand(Light.off);
那么是否需要把命令包装成通用方法excute呢?这个主要看我是否需要记录命令执行过程,或状态。
3、案例:命令模式记录执行过程,执行完重演,并且打印执行个数。
这里就要用闭包创建一个对象,此对象拥有三个功能,一个是执行单个方法excute,一个是重复执行所有方法reset,还有一个方法返回计数count,串联这三个方法是由二个闭包私有变量完成的,一个是cache数组,用来装执行过的命令,一个是size数值变量,用来记录操作的次数。
var excutes = (function() { var cache = []; var size = 0; var excute , reset , count, excute = function(comand) { comand && comand.excute(); size++; cache.push(comand); }; reset = function() { cache.forEach(ele=>{ ele && ele.excute(); }); }; count = function() { return size; }; return { excute,reset,count, }; })();
// 执行过程的代号 var excute_indexs = [0,1,1,0,1,1]; // 命令包装 var c1 = new CommandOn(Light); var c2 = new CommandOff(Light); // 命令组包装命令(用代号表示) var commands = { [1]: c1, [0]: c2, }
测试
// 测试:顺序执行 excute_indexs.forEach(ele=>{ excutes.excute(commands[ele]); }); console.log('.........................') // 测试:重复执行已经执行过的 excutes.reset(); console.log('.........................') console.log(excutes.count());
转载地址:http://deuni.baihongyu.com/