单体模式提供了一种将代码组织为一个逻辑单元的手段,这个逻辑单元中的代码可以通过单一变量进行访问。
单体模式的优点是:
什么是单体模式?单体模式是一个用来划分命名空间并将一批属性和方法组织在一起的对象,如果它可以被实例化,那么它只能被实例化一次。
但是并非所有的对象字面量都是单体,比如说模拟数组或容纳数据的话,那么它就不是单体,但是如果是组织一批相关的属性和方法在一起的话,那么它有可能是单体模式,所以这需要看开发者编写代码的意图;
下面我们来看看定义一个对象字面量(结构类似于单体模式)的基本结构如下:
// 对象字面量 var Singleton = { attr1: 1, attr2: 2, method1: function(){ return this.attr1; }, method2: function(){ return this.attr2; } };
如上面只是简单的字面量结构,上面的所有成员变量都是通过Singleton来访问的,但是它并不是单体模式;因为单体模式还有一个更重要的特点,就是可以仅被实例化一次,上面的只是不能被实例化的一个类,因此不是单体模式;对象字面量是用来创建单体模式的方法之一;
使用单体模式的结构如下demo
我们明白的是单体模式如果有实例化的话,那么只实例化一次,要实现一个单体模式的话,我们无非就是使用一个变量来标识该类是否被实例化,如果未被实例化的话,那么我们可以实例化一次,否则的话,直接返回已经被实例化的对象。
如下代码是单体模式的基本结构:
// 单体模式 var Singleton = function(name){ this.name = name; this.instance = null; }; Singleton.prototype.getName = function(){ return this.name; } // 获取实例对象 function getInstance(name) { if(!this.instance) { this.instance = new Singleton(name); } return this.instance; } // 测试单体模式的实例 var a = getInstance("aa"); var b = getInstance("bb");
// 因为单体模式是只实例化一次,所以下面的实例是相等的 console.log(a === b); // true
由于单体模式只实例化一次,因此第一次调用,返回的是a实例对象,当我们继续调用的时候,b的实例就是a的实例,因此下面都是打印的是aa;
console.log(a.getName());// aa console.log(b.getName());// aa
上面的封装单体模式也可以改成如下结构写法:
// 单体模式 var Singleton = function(name){ this.name = name; }; Singleton.prototype.getName = function(){ return this.name; } // 获取实例对象 var getInstance = (function() { var instance = null; return function(name) { if(!instance) { instance = new Singleton(name); } return instance; } })(); // 测试单体模式的实例 var a = getInstance("aa"); var b = getInstance("bb"); // 因为单体模式是只实例化一次,所以下面的实例是相等的 console.log(a === b); // true console.log(a.getName());// aa console.log(b.getName());// aa
理解使用代理实现单列模式的好处
比如我现在页面上需要创建一个div的元素,那么我们肯定需要有一个创建div的函数,而现在我只需要这个函数只负责创建div元素,其他的它不想管,也就是想实现单一职责原则,就好比淘宝的kissy一样,一开始的时候他们定义kissy只做一件事,并且把这件事做好,具体的单体模式中的实例化类的事情交给代理函数去处理,这样做的好处是具体的业务逻辑分开了,代理只管代理的业务逻辑,在这里代理的作用是实例化对象,并且只实例化一次; 创建div代码只管创建div,其他的不管;如下代码:
// 单体模式 var CreateDiv = function(html) { this.html = html; this.init(); } CreateDiv.prototype.init = function(){ var div = document.createElement("div"); div.innerHTML = this.html; document.body.appendChild(div); }; // 代理实现单体模式 var ProxyMode = (function(){ var instance; return function(html) { if(!instance) { instance = new CreateDiv("我来测试下"); } return instance; } })(); var a = new ProxyMode("aaa"); var b = new ProxyMode("bbb"); console.log(a===b);// true
理解使用单体模式来实现弹窗的基本原理
下面我们继续来使用单体模式来实现一个弹窗的demo;我们先不讨论使用单体模式来实现,我们想下我们平时是怎么编写代码来实现弹窗效果的; 比如我们有一个弹窗,默认的情况下肯定是隐藏的,当我点击的时候,它需要显示出来;如下编写代码:
// 实现弹窗 var createWindow = function(){ var div = document.createElement("div"); div.innerHTML = "我是弹窗内容"; div.style.display = 'none'; document.body.appendChild('div'); return div; }; document.getElementById("Id").onclick = function(){ // 点击后先创建一个div元素 var win = createWindow(); win.style.display = "block"; }
如上的代码;大家可以看看,有明显的缺点,比如我点击一个元素需要创建一个div,我点击第二个元素又会创建一次div,我们频繁的点击某某元素,他们会频繁的创建div的元素,虽然当我们点击关闭的时候可以移除弹出代码,但是呢我们频繁的创建和删除并不好,特别对于性能会有很大的影响,对DOM频繁的操作会引起重绘等,从而影响性能;因此这是非常不好的习惯;我们现在可以使用单体模式来实现弹窗效果,我们只实例化一次就可以了;如下代码:
// 实现单体模式弹窗 var createWindow = (function(){ var div; return function(){ if(!div) { div = document.createElement("div"); div.innerHTML = "我是弹窗内容"; div.style.display = 'none'; document.body.appendChild(div); } return div; } })(); document.getElementById("Id").onclick = function(){ // 点击后先创建一个div元素 var win = createWindow(); win.style.display = "block"; }
理解编写通用的单体模式
上面的弹窗的代码虽然完成了使用单体模式创建弹窗效果,但是代码并不通用,比如上面是完成弹窗的代码,假如我们以后需要在页面中一个iframe呢?我们是不是需要重新写一套创建iframe的代码呢?比如如下创建iframe:
var createIframe = (function(){ var iframe; return function(){ if(!iframe) { iframe = document.createElement("iframe"); iframe.style.display = 'none'; document.body.appendChild(iframe); } return iframe; }; })();
我们看到如上代码,创建div的代码和创建iframe代码很类似,我们现在可以考虑把通用的代码分离出来,使代码变成完全抽象,我们现在可以编写一套代码封装在getInstance函数内,如下代码:
var getInstance = function(fn) { var result; return function(){ return result || (result = fn.call(this,arguments)); } };
如上代码:我们使用一个参数fn传递进去,如果有result这个实例的话,直接返回,否则的话,当前的getInstance函数调用fn这个函数,是this指针指向与这个fn这个函数;之后返回被保存在result里面;现在我们可以传递一个函数进去,不管他是创建div也好,还是创建iframe也好,总之如果是这种的话,都可以使用getInstance来获取他们的实例对象;
如下测试创建iframe和创建div的代码如下:
// 创建div var createWindow = function(){ var div = document.createElement("div"); div.innerHTML = "我是弹窗内容"; div.style.display = 'none'; document.body.appendChild(div); return div; }; // 创建iframe var createIframe = function(){ var iframe = document.createElement("iframe"); document.body.appendChild(iframe); return iframe; }; // 获取实例的封装代码 var getInstance = function(fn) { var result; return function(){ return result || (result = fn.call(this,arguments)); } }; // 测试创建div var createSingleDiv = getInstance(createWindow); document.getElementById("Id").onclick = function(){ var win = createSingleDiv(); win.style.display = "block"; }; // 测试创建iframe var createSingleIframe = getInstance(createIframe); document.getElementById("Id").onclick = function(){ var win = createSingleIframe(); win.src = "http://www.jb51.com"; };
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍javascript设计模式之策略模式学习笔记,包括了javascript设计模式之策略模式学习笔记的使用技巧和注意事项,需要的朋友参考一下 1. 理解javascript中的策略模式 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。 使用策略模式的优点如下: 优点: 1. 策略模式利用组合,委托等技术和思想,有效的避免很多if条件语句。
本文向大家介绍javascript设计模式之中介者模式学习笔记,包括了javascript设计模式之中介者模式学习笔记的使用技巧和注意事项,需要的朋友参考一下 先来理解这么一个问题,假如我们前端开发接的需求是需求方给我们需求,可能一个前端开发会和多个需求方打交道,所以会保持多个需求方的联系,那么在程序里面就意味着保持多个对象的引用,当程序的规模越大,对象会越来越多,他们之间的关系会越来越复杂,那
本文向大家介绍学习JavaScript设计模式之策略模式,包括了学习JavaScript设计模式之策略模式的使用技巧和注意事项,需要的朋友参考一下 把不变的部分和变化的部分隔开是每个设计模式的主题。 条条大路通罗马。我们经常会遇到解决一件事情有多种方案,比如压缩文件,我们可以使用zip算法、也可以使用gzip算法。其灵活多样,我们可以采用策略模式解决。 一、定义 定义一系列的算法,把它们一个个封装
本文向大家介绍学习JavaScript设计模式之代理模式,包括了学习JavaScript设计模式之代理模式的使用技巧和注意事项,需要的朋友参考一下 明星都有经纪人作为代理。如果请明星办一场商演,只能联系其经纪人,经纪人会把商演的细节和报酬谈好,再把合同交给明星签。 一、定义 代理模式:为一个对象提供一个代用品或占位符,以便控制对它的访问。 代理分为:保护代理和虚拟代理 保护代理:用于控制不同权限的
本文向大家介绍学习JavaScript设计模式之享元模式,包括了学习JavaScript设计模式之享元模式的使用技巧和注意事项,需要的朋友参考一下 一、定义 享元(flyweight)模式是一种用于性能优化的模式,核心是运用共享技术来有效支持大量细刻度的对象。 在JavaScript中,浏览器特别是移动端的浏览器分配的内存并不算多,如何节省内存就成了一个非常有意义的事情。 享元模式是一种用时间换空
本文向大家介绍学习JavaScript设计模式之状态模式,包括了学习JavaScript设计模式之状态模式的使用技巧和注意事项,需要的朋友参考一下 状态模式的关键是区分事物内部的状态,事物内部状态的改变往往会带来事物的行为改变。 当电灯开着,此时按下开关,电灯会切换到关闭状态;再按一次开关,电灯又将被打开。同一个开关在不同的状态下,表现出来的行为是不一样的。 一、有限状态机 状态总数(state)