js 设计模式——单例模式
程序员文章站
2023-11-11 00:00:28
单例模式 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的 window 对象等。 JavaScript 中的单例模式 1. 使用命名空间 在JavaScript里,实现单例的方式有很多种,其中最简单的一 ......
单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的 window 对象等。
javascript 中的单例模式
1. 使用命名空间
在javascript里,实现单例的方式有很多种,其中最简单的一个方式是使用对象字面量的方法,其字面量里可以包含大量的属性和方法:
let people = { name: "jack", age: 18, play() { console.log('i like game'); } }
还可以动态地创建命名空间
// 定义对象 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' ); /******************* 上面没看懂没关系 ***********************/ // 上述代码等价于 var myapp = { event: {}, dom: { style: {} } };
2. 使用闭包封装私有变量
var user = (function(){ var __name = 'sven', __age = 29; return { getuserinfo: function(){ return __name + '-' + __age; } } })();
我们用下划线来约定私有变量 __name
和 __age
,它们被封装在闭包产生的作用域中,外部是访问不到这两个变量的,这就避免了对全局的命令污染。
实现一个标准的单例模式
var singleton = function( name ){ this.name = name; this.instance = null; }; singleton.prototype.getname = function(){ alert ( this.name ); }; singleton.getinstance = function( name ){ if ( !this.instance ){ this.instance = new singleton( name ); } return this.instance; }; var a = singleton.getinstance( 'sven1' ); var b = singleton.getinstance( 'sven2' ); alert ( a === b ); // true
我们通过 singleton.getinstance
来获取 singleton
类的唯一对象,这种方式相对简单,但有一个问题,就是增加了这个类的“不透明性”, singleton
类的使用者必须知道这是一个单例类,跟以往通过 new xxx
的方式来获取对象不同,这里偏要使用 singleton.getinstance
来获取对象。
透明的单例模式
var creatediv = (function(){ var instance; var creatediv = function( html ){ if ( instance ){ return instance; } this.html = html; this.init(); 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( 'sven1' ); var b = new creatediv( 'sven2' ); alert ( a === b ); // true
为了把 instance
封装起来,我们使用了自执行的匿名函数和闭包,并且让这个匿名函数返回
真正的 singleton
构造方法,这增加了一些程序的复杂度
3. 用代理实现单例模式
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 ); }; // 代理类 proxysingletoncreatediv: var proxysingletoncreatediv = (function(){ var instance; return function( html ){ if ( !instance ){ instance = new creatediv( html ); } return instance; } })(); var a = new proxysingletoncreatediv( 'sven1' ); var b = new proxysingletoncreatediv( 'sven2' ); alert ( a === b );
通过引入代理类的方式,我们同样完成了一个单例模式的编写,跟之前不同的是,现在我们
把负责管理单例的逻辑移到了代理类 proxysingletoncreatediv
中。这样一来,creatediv
就变成了一个普通的类,它跟 proxysingletoncreatediv
组合起来可以达到单例模式的效果。
惰性单例
惰性单例指的是在需要的时候才创建对象实例。
var singleton = (function () { var instantiated; function init() { /*这里定义单例代码*/ return { publicmethod: function () { console.log('hello world'); }, publicproperty: 'test' }; } return { getinstance: function () { if (!instantiated) { instantiated = init(); } return instantiated; } }; })(); /*调用公有的方法来获取实例:*/ singleton.getinstance().publicmethod();
通过以上方法我们就可以做到只有在使用的时候才初始化,从而达到节约资源的目的
目前对于单例模式的理解就这么多,以后有了新的理解会继续更新的,溜了溜了(~ ̄▽ ̄)~