JavaScript设计模式----单例模式

来源:互联网 发布:淘宝如何下降退货率 编辑:程序博客网 时间:2024/06/06 03:28

声明:这个系列为阅读《JavaScript设计模式与开发实践》 —-曾探@著一书的读书笔记

1.单例模式的特点和定义

保证一个类仅有一个实例,并且提供一个访问它的全局访问点。

2.传统面向对象语言的单例模式

2.1传统语言描述的单例模式JavaScript实现

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('seven1');var b = Singleton.getInstance('seven2');

或者使用闭包的形式创建单例模式,同时符合惰性单例的特性

var Singleton = function(name) {    this.name = name;};Singleton.prototype.getName = function() {    alert(this.name);};//利用闭包的特性创建单例,同时符合惰性单例的特性Singleton.getInstance = (function(name) {    var instance;    return function(name){        if (!instance) {            instance = new Singleton(name);        }    }})();var a = Singleton.getInstance('seven1');var b = Singleton.getInstance('seven2');console.log(a===b);   //true

2.2透明的单例模式:

//反面的单例模式的例子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('seven1');var b = new CreateDiv('seven2');

这样编写单例模式的缺点:

为了把instance封装起来,我们使用了自执行的匿名函数和闭包,并且让这个匿名函数返回真正的Singleton构造方法,这增加了一些程序的复杂度。

CreateDiv的构造函数负责了两件事情。1.创建对像和执行初始化init方法,第二是保证只有一个对象。不符合设计模式中的单一职责的概念。

2.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);}var ProxySingletonCreateDiv = (function() {    var instance;    return function(html) {        if (!instance) {            instance = new CreateDiv(html);        }        return instance;    }})();var a = new ProxySingletonCreateDiv('seven1');var b = new ProxySingletonCreateDiv('seven2');

引入代理实现单例模式的特点:

我们负责管理单例的逻辑移到了代理类ProxySingletonCreateDiv中。这样一来,CreateDiv就变成了一个普通的类,他跟ProxySingletonCreateDiv组合起来可以达到单例模式的效果。

3.JavaScript的单例模式对比

在以上的代码中实现的单例模式都混入了传统面向对象语言的特点。而没有利用JavaScript这们语言的特点来实现一个单例模式。

3.1惰性单例的例子

概念描述:

惰性单例指的是在需要的时候才创建对象的实例。惰性单例是单例模式的重点。

var createLoginLayer=(function(){    var div;    return function(){        if(!div){            div=document.createElement('div');            //创建一个登录框        }        return div;    }})();document.getElementById('loginBtn').onclick=function(){    var loginLayer=createLoginLayer();    loginLayer.style.display='block';};

代码解析:
这里的对惰性单例的实现主要是只有单例了网页上的登录按钮,才会去创建,登录框的dom节点,并且只是创建一次。

3.2通用的单例模式例子

根据3.1的代码示例,我们的单例对像,但是并不是通用的,比如我们要创建的不是div而是iframe,那要怎么办呢?

//获取单例var getSingle = function(fn){    var result;    return function (){        return result || (result=fn.apply(this,arguments));    };};//创建div登录框var createLoginLayer=function (){    var div= document.createElement('div');    div.innerHTML='我是登录框';    document.body.appendChild(div);    return div;};//创建iframe的dom节点var createIframe=function(){    //创建irame节点的代码}var createSingleLoginLayer = getSingle(createLoginLayer);var createSingleIframe=getSingle(createIframe);var loginLayer1 = createSingleLoginLayer();var loginLayer2 = createSingleLoginLayer();var iframe1=createSingleIframe();var iframe2=createSingleIframe();console.log(loginLayer1 === loginLayer2);

通用的单例创建的例子就是通过封装一个getSingle需要实现单例模式的对象。而且只是会只创建一次。因为使用了闭包的原因通过getSingle创建的result会在内存中一直存在不会销毁(除非页面关闭,或者手动释放)。

总结:

单例模式是一种简单但非常实用的模式,特别是惰性单例技术,在合适的时候才创建对像,并且只创建唯一的一个。更奇妙的是,创建对象和管理单例的职责被分布在两个不同的方法中,这两个方法组合起来才具有单例模式的威力。


图片名称

1 0
原创粉丝点击