//getSingle运用到了闭包和高阶函数。创建对象和管理单例的职责被分布在两个不同的方法中
var getSingle = function (fn) {
var result;
return function () {
return result || (result = fn.apply(this, arguments));
};
};
策略模式
策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
//这里将不同的的算法提取出来,在调用时确定要执行的是哪个算法,需要使用者对各个策略都要了解,才能选择合适的策略
var S = function( salary ){
return salary * 4;
};
var A = function( salary ){
return salary * 3;
};
var B = function( salary ){
return salary * 2;
};
var calculateBonus = function( func, salary ){
return func( salary );
};
calculateBonus( S, 10000 );
var setCommand = function (button, func) {
button.onclick = function () {
func();
};
};
var MenuBar = {
refresh: function () {
console.log("刷新菜单界面");
},
};
var RefreshMenuBarCommand = function (receiver) {
return function () {
receiver.refresh();
};
};
var refreshMenuBarCommand = RefreshMenuBarCommand(MenuBar);
setCommand(button1, refreshMenuBarCommand);
组合模式就是用小的子对象来构建更大的对象,而这些小的子对象本身也许是由更
小的“孙对象”构成的。例如文件夹,就是一种组合
var folder = new Folder( '学习资料' );
var folder1 = new Folder( 'JavaScript' );
var folder2 = new Folder ( 'jQuery' );
var file1 = new File( 'JavaScript 设计模式与开发实践' );
var file2 = new File( '精通 jQuery' );
var file3 = new File( '重构与模式' )
folder1.add( file1 );
folder2.add( file2 );
folder.add( folder1 );
folder.add( folder2 );
folder.add( file3 );
这篇内容,是针对这本书中提到的设计模式及原则进行截取,并展示文中的代码,以便复习巩固。
涉及的模式:
单例模式,策略模式,代理模式,迭代器模式,发布-订阅模式,命令模式,组合模式,模板方法模式,享元模式,职责链模式,中介者模式,装饰者模式,状态模式,适配器模式
涉及的原则:
单一责任原则,最少知识原则,开放封闭原则
模式
分辨模式的关键是意图而不是结构
设计模式分别被划分为创建型模式、结构型模式和行为型模式。 拿创建型模式来说,要创建一个对象,是一种抽象行为,而具体创建什么对象则是可以变化的
单例模式
单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
策略模式
策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
代理模式
代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对象。在 JavaScript 开发中最常用的是虚拟代理和缓存代理。 需强调:代理和本体接口的一致性,因为对于客户来说,对代理和本体是不感知的,并且当需求变更,不再需要代理时,可能很方便得去除代理或直接请求本体
迭代器模式
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。 迭代器可以分为内部迭代器和外部迭代器,js中的foreach就是内部迭代器,es6中的generator就是外部迭代器。内部迭代器在调用的时候非常方便,但规则已限定,不够灵活。外部迭代器增加了一些调用的复杂度,但相对也增强了迭代器的灵活性。
发布-订阅模式
发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状 态发生改变时,所有依赖于它的对象都将得到通知。但两者又有细微的差别,观察者模式存在目标和观察者,当事件触发时,目标直接调用观察者的事件。发布—订阅模式中存在了发布者,订阅者,调度中心,发布者和订阅者对彼此完全无感知,统一都是由调度中心进行处理,类似于中介者模式,但在目的上又有所不同。
命令模式
命令模式中的命令(command)指的是一个执行某些特定事情的指令。命令模式的由来,其实是回调(callback)函数的一个面向对象的替代品。 命令模式的意图是把请求封装为对象,从而分离请求的发起者和请求的接收者(执行者)之 间的耦合关系。在命令被执行之前,可以预先往命令对象中植入命令的接收者。
组合模式就是用小的子对象来构建更大的对象,而这些小的子对象本身也许是由更
小的“孙对象”构成的。例如文件夹,就是一种组合
模板方法模式
模板方法模式:一种基于继承的设计模式。模板方法模式由两部分结构组成,第一部分是抽象父类,第二部分是具体的实现子类。像vue和react中的生命周期,其实就是模板方法的体现,它们各自设定好对应的接口,并在合适的时机调用,而我们只需要在子类中定义好具体的实现就行了
享元模式
享元模式是一种用于性能优化的模式,享元模式的核心是运用共享技术来有效支持大量细粒度的对象。 享元模式要求将对象的属性划分为内部状态与外部状态(状态在这里通常指属性)。享元模式的目标是尽量减少共享对象的数量,关于如何划分内部状态和外部状态,下面的几条经验提供了一些指引。
职责链模式
职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间 的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
//优化 var order500 = function (orderType, pay, stock) { if (orderType === 1 && pay === true) { console.log("500 元定金预购,得到 100 优惠券"); } else { return "nextSuccessor"; // 我不知道下一个节点是谁,反正把请求往后面传递 } }; var order200 = function (orderType, pay, stock) { if (orderType === 2 && pay === true) { console.log("200 元定金预购,得到 50 优惠券"); } else { return "nextSuccessor"; // 我不知道下一个节点是谁,反正把请求往后面传递 } }; var orderNormal = function (orderType, pay, stock) { if (stock > 0) { console.log("普通购买,无优惠券"); } else { console.log("手机库存不足"); } }; var Chain = function( fn ){ this.fn = fn; this.successor = null; }; Chain.prototype.setNextSuccessor = function( successor ){ return this.successor = successor; }; Chain.prototype.passRequest = function(){ var ret = this.fn.apply( this, arguments ); if ( ret === 'nextSuccessor' ){ return this.successor && this.successor.passRequest.apply( this.successor, arguments ); } return ret; }; //现在我们把 3 个订单函数分别包装成职责链的节点: var chainOrder500 = new Chain( order500 ); var chainOrder200 = new Chain( order200 ); var chainOrderNormal = new Chain( orderNormal ); //然后指定节点在职责链中的顺序: chainOrder500.setNextSuccessor( chainOrder200 ); chainOrder200.setNextSuccessor( chainOrderNormal ); //最后把请求传递给第一个节点: chainOrder500.passRequest( 1, true, 500 ); // 输出:500 元定金预购,得到 100 优惠券 chainOrder500.passRequest( 2, true, 500 ); // 输出:200 元定金预购,得到 50 优惠券 chainOrder500.passRequest( 3, true, 500 ); // 输出:普通购买,无优惠券 chainOrder500.passRequest( 1, false, 0 ); // 输出:手机库存不足