单利模式:保证一个类只有一个实例,并提供一个访问它的全局访问点。好今天我们就来领会下这个单例模式
实现单例模式: 就是利用一个变量来标记当前是否已经为某个类创建的对象,如果是,则在下次获取该类实例时,直接返回之前创建的对象1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var Singleton = function (name ) { this .name = name; this .instance = null ; }; Singleton.prototype.getName = function ( ) { console .log( this .name ) } Singleton.getInstance = function (name ) { if ( !this .instance ){ this .instance = new Singleton(name); } return this .instance; }; var a = Singleton.getInstance('zhu' );var b = Singleton.getInstance('wang' );console .log( a === b )
不过上面这个实现并不友好:通过Singleton.getInstance来获Singleton类的唯一对象,但是增加了类的不透明性
,Singleton类的使用者必须知道其为单例类,,不能通过new XXX
的形式来获取对象><
实现透明单例模式: 透明单例就是用户可以像使用普通类一样,从这个类中创建对象1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 var CreateDiv = (function ( ) {var instance;var CreateDiv = function ( html ) { if ( instance ){ return instance; } this .html = html; this .init(); console .log(this ) return instance = this ; }; CreateDiv.prototype.init = function ( ) { var div = document .createElement('div' ); div.innerHTML = this .html; document .body.appendChild( div ); } return CreateDiv;}()) var a = new CreateDiv('zhu' );var b = new CreateDiv('wang' );console .log( a===b )
但是上面的代码也同样存在缺点,看下面这个代码:1 2 3 4 5 6 7 8 9 var CreateDiv = function ( html ) { if ( instance ){ return instance; } this .html = html; this .init(); console .log(this ) return instance = this ; };
他违反了单一职责原则:既要创建对象,并进行初始化方法,又要保证只有一个对象>><<
用代理实现单例模式: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 ProxySingletonCreateDiv = (function ( ) { var instance; return function (html ) { if (!instance){ instance = new CreateDiv(html); } return instance; } }()) var a = new ProxySingletonCreateDiv('zhu' );var b = new ProxySingletonCreateDiv('wang' );console .log( a === b )
将负责管理单例的逻辑放到独立的一个类,,使原来的createDiv成为一个普通类
javascript中的单例模式 js中的全局变量很容易造成变量污染,用如下的方式可以减少命名污染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 var nameSpace = {a : function ( ) { alert(1 ); }, b:function ( ) { alert(2 ); } }; var Myapp = {};Myapp.nameSpace = function (name ) { var parts = name.split('.' ); var current = Myapp; for (var i in parts){ if (!current[ parts[i] ]){ current[ parts[i] ] = {}; } current = current[ parts[i] ]; } }; Myapp.nameSpace('event' ); Myapp.nameSpace('dom.style' ); console .dir(Myapp)Myapp = { event : {}, dom:{ style:{} } } */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <!DOCTYPE html> <html > <head > <meta charset ="utf-8" > <meta http-equiv ="X-UA-Compatible" content ="IE=edge" > <title > </title > <link rel ="stylesheet" href ="" > </head > <body > <button id ='loginBtn' > 登入</button > <script > var createQQ = (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('loginBtn' ).onclick = function () { var loginLayer = createQQ(); loginLayer.style.display = 'block' }*/ </script > </body > </html >
通用的惰性单例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var createDiv = function ( ) {var div = document .createElement('div' );div.innerHTML = '你正在登陆' ; div.style.display = 'none' ; document .body.appendChild(div);return div;}; var getSingleton = function (fn ) { var result; return function ( ) { return result || (result = fn.apply(this ,arguments )); } }; var createSingleLoginLayer = getSingleton( createDiv );document .getElementById('loginBtn' ).onclick = function ( ) { var loginLayer = createSingleLoginLayer(); loginLayer.style.display = 'block' }
另外tom大叔 也有一篇关于单例模式的介绍,可以去学习学习
<
毛玻璃
续谈闭包
>