对几种常见的设计模式的理解 (javascript实现)
设计模式的核心原则:
- 单一职责原则(SRP)
- 一个对象(方法)只做一件事情
- 开放-封闭原则(OCP)
- 软件实体(类、模块、函数)等应该是可以扩展的,但是不可修改。
- 最少知识原则(LKP)
- 一个软件实体应当尽可能少地与其他实体发生相互作用。(调用链不要太长和过于复杂)
- 比如(情景:将军需要让(士兵 function)挖散兵坑)
- (复杂的情况)将军通知上校让他叫来少校,然后让少校找来上尉,并让上尉通知一个军士,最后军士唤来一个士兵,然后将军命令士兵挖掘一些散兵坑。
- (简单情况)将军有个调度部,命令调度部去挖掘一些散兵坑就行了,调度部会安排士兵去
- 一个软件实体应当尽可能少地与其他实体发生相互作用。(调用链不要太长和过于复杂)
几种常见的设计模式:
- 单例模式
- 迭代器模式
- 代理(中介)模式
- 发布-订阅模式
- 装饰器模式
1. 单例模式
定义:确保一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的window对象等
在JavaScript开发中,单例模式的用途非常广泛。试想一下,当我们单击登录按钮的时候,页面中会出现一个登录浮窗,而这个登录浮窗是唯一的,无论单击多少次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗就适合用单例模式来创建。
单个单例参考:
// 单例构造函数function CreateSingleton (name) {this.name = name;this.getName();};// 获取实例的名字CreateSingleton.prototype.getName = function() {console.log(this.name)};// 单例对象var Singleton = (function(){ // 用闭包特性,保存唯一的单例var instance; // 保存唯一的单例return function (name) {if(!instance) {instance = new CreateSingleton(name);}return instance;}})();// 创建实例对象1var a = new Singleton('a');// 创建实例对象2var b = new Singleton('b');console.log(a === b); // true
通用单例参考:
var singleton = function(fn) {var instance;return function() {return instance || (instance = fn.apply(this, arguments));}};// 创建遮罩层var createMask = function(){// 创建div元素var mask = document.createElement('div');// 设置样式mask.style = 'xxx'document.body.appendChild(mask);// 单击隐藏遮罩层mask.onclick = function(){this.style.display = 'none';}return mask;};// 创建登陆窗口var createLogin = function() {// 创建div元素var login = document.createElement('div');// 设置样式login.style = 'xxx'login.innerHTML = 'login it';document.body.appendChild(login);return login;};document.getElementById('btn').onclick = function() {singleton(createMask)();singleton(createLogin)();}
总结:需要有一个变量去保存单例
2. 迭代器模式
可以很简便的实现遍历
- js也内置了迭代器(some、every、forEach、map、filter)等
// 手动实现一个迭代器var each = function(ary, callback){for (var i = 0, l = ary.length; i < l; i++){if (callback.call(ary[i], i, ary[i]) === false){ // callback 的执行结果返回false,提前终止迭代break;}}};each([1, 2, 3, 4, 5], function(i, n){if (n > 3){ // n 大于3 的时候终止循环return false;}console.log(n); // 分别输出:1, 2, 3});
3. 代理(中介)模式
为一个对象提供一个代用品或占位符,以便控制对它的访问
代理模式是一种非常有意义的模式,在生活中可以找到很多代理模式的场景。
- 比如,明星都有经纪人作为代理。如果想请明星来办一场商业演出,只能联系他的经纪人。经纪人会把商业演出的细节和报酬都谈好之后,再把合同交给明星签。
代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对象。替身对象对请求做出一些处理之后,再把请求转交给本体对象

举个实际例子:
- 通过增加虚拟代理的方式,把预加载图片的职责放到代理对象中,而本体仅仅负责往页面中添加img标签,这也是它最原始的职责。
此例子是:我们需要加载一个大图,大图比较慢,在大图未加载好之前,先用菊花图loading.gif替代
// myImage负责往页面中添加img标签:var myImage = (function(){var imgNode = document.createElement( 'img' );document.body.appendChild( imgNode );return {setSrc: function( src ) {imgNode.src = src;}}})();// proxyImage负责预加载图片,并在预加载完成之后把请求交给本体myImage:var proxyImage = (function() {var img = new Image;img.onload = function() {myImage.setSrc( this.src );}return {setSrc: function( src ) {myImage.setSrc( './loading.gif' );img.src = src;}}})();proxyImage.setSrc( 'http://imgcache.qq.com/music/photo/xxxxxxbig.png' );
4. 发布-订阅模式(观察者模式)
博主姊妹篇:发布-订阅模式详解(观察者模式)
5. 装饰器模式
其他伙伴写的:https://segmentfault.com/a/1190000013664124
个人整理,有误可留言。
部分参考丛书 《JavaScript设计模式与开发实践》曾探
