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( ‘sven1‘ );
var b = Singleton.getInstance( ‘sven2‘ );
alert ( a === b ); // true

或者:

var Singleton = function(name){
  this.name = name;
};
Singleton.prototype.getName = function(){
  alert(this.name);
};
Singleton.getInstance = (function(){
  var instance = null;
  return function( name ){
    if ( !instance ){
      instance = new Singleton( name );
    }
    return instance;
  }
})();
var a = Singleton.getInstance( ‘sven1‘ );
var b = Singleton.getInstance( ‘sven2‘ );
alert ( a === b ); // true

以上虽然是一个简单的“不透明”单例模式,但是在实际项目中的意义不大。

二、透明的单例模式:

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

在这段代码中,CreateDiv 的构造函数实际上负责了两件事情:第一是创建对象和执行初始化 init 方法,第二是保证只有一个对象。

虽然我们目前还没有接触过“单一职责原则”的概念, 但可以明确的是,这是一种不好的做法,至少这个构造函数看起来很奇怪。

假设我们某天需要利用这个类,在页面中创建千千万万的 div,即要让这个类从单例类变成 一个普通的可产生多个实例的类,那我们必须得改写 CreateDiv 构造函数,把控制创建唯一对象 的那一段去掉,这种修改会给我们带来不必要的烦恼。

三:用代理实现单例模式:

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‘ );
console.log( a === b );

通过引入代理类的方式,我们同样完成了一个单例模式的编写,跟之前不同的是,现在我们 把负责管理单例的逻辑移到了代理类 proxySingletonCreateDiv 中。

这样一来,CreateDiv 就变成了 一个普通的类,它跟 proxySingletonCreateDiv 组合起来可以达到单例模式的效果。

四、js中的单例模式:

前面提到的几种单例模式的实现,更多的是接近传统面向对象语言中的实现,单例对象从 “类”中创建而来。在以类为中心的语言中,这是很自然的做法。比如在 Java 中,如果需要某个对象,就必须先定义一个类,对象总是从类中创建而来的。

但 JavaScript 其实是一门无类(class-free)语言,也正因为如此,生搬单例模式的概念并无 意义。在 JavaScript 中创建对象的方法非常简单,既然我们只需要一个“唯一”的对象,为什 么要为它先创建一个“类”呢?这无异于穿棉衣洗澡,传统的单例模式实现在 JavaScript 中并 不适用。单例模式的核心是确保只有一个实例,并提供全局访问。

全局变量不是单例模式,但在 JavaScript 开发中,我们经常会把全局变量当成单例来使用。例如:var a = {};当用这种方式创建对象 a 时,对象 a 确实是独一无二的。如果 a 变量被声明在全局作用域下, 则我们可以在代码中的任何位置使用这个变量,全局变量提供给全局访问是理所当然的。这样就满足了单例模式的两个条件。但是全局变量存在很多问题,它很容易造成命名空间污染。使用两种方法可以避免变量的全局污染:

1、使用命名空间:适当地使用命名空间,并不会杜绝全局变量,但可以减少全局变量的数量。

var namespace1 = {
    a: function(){
        alert (1);
    },
    b: function(){
        alert (2);
    }
};    

2、使用闭包封装私有变量

var user = (function(){
  var __name = ‘sven‘,
    __age = 29;
  return {
    getUserInfo: function(){
      return __name + ‘-‘ + __age;
    }
  }
})();

五、惰性单例:

惰性单例指的是在需要的时候才创建对象实例。惰性单例是单例模式的重点,这种技术在实际开发中非常有用。

我们可以将管理单例的逻辑从原来的代码中抽离出来:

var getSingle = function( fn ){
  var result;
  return function(){
    return result || ( result = fn .apply(this, arguments ) );
  }
};

将创建登录浮窗的方法用参数 fn 的形式传入 getSingle,我们不仅可以传入 createLoginLayer,还能传入 createScript、createIframe、createXhr 等。之后再让 getSingle 返回 一个新的函数,并且用一个变量 result 来保存 fn 的计算结果。result 变量因为身在闭包中,它永远不会被销毁。在将来的请求中,如果 result 已经被赋值,那么它将返回这个值。

创建弹窗:var createLoginLayer = function(){
  var div = document.createElement( ‘div‘ );
  div.innerHTML = ‘我是登录浮窗‘;
  div.style.display = ‘none‘;
  document.body.appendChild( div );
  return div;
};
var createSingleLoginLayer = getSingle(createLoginLayer);
document.getElementById( ‘loginBtn‘ ).onclick = function(){
  var loginLayer = createSingleLoginLayer();
  loginLayer.style.display = ‘block‘;
};

创建iframe:
var createSingleIframe = getSingle( function(){
  var iframe = document.createElement ( ‘iframe‘ );
  document.body.appendChild( iframe );
  return iframe;
});
document.getElementById( ‘loginBtn‘ ).onclick = function(){
  var loginLayer = createSingleIframe();
  loginLayer.src = ‘http://baidu.com‘;
};

在这个例子中,我们把创建实例对象的职责和管理单例的职责分别放置在两个方法里,这两个方法可以独立变化而互不影响,当它们连接在一起的时候,就完成了创建唯一实例对象的功能。

原文地址:https://www.cnblogs.com/angelatian/p/11770362.html

时间: 2024-10-02 02:13:38

JavaScript设计模式(单例模式)的相关文章

javascript设计模式-单例模式

单例模式,是创建型设计模式的一种,又被称为单体模式,是只允许实例化一次的对象类.有时也用来规划一个命名空间. 1 var Util = { 2 getName: function () { 3 console.log('wp') 4 }, 5 getAge: function () { 6 console.log(25) 7 }, 8 getAll: function () { 9 this.getName(); 10 this.getAge(); 11 } 12 } 13 Wang.getAl

[读书笔记] JavaScript设计模式: 单例模式

单例模式:保证一个类只有一个实例,并提供一个可以访问它的全局访问点. 一种简单.方便的写法就是用一个变量来标识当前类是否已经创建过对象,如果有,则返回已经创建好的对象,否则创建一个新对象,并将其返回. var Singleton = function(name) { this.name = name; this.instance = null; } Singleton.prototype.getName = function() { alert(this.name); } Singleton.g

JavaScript 设计模式 - 单例模式

单例模式 用于保存全局变量,减少内存使用等 [实现代码] var MyNameSpace = {}; MyNameSpace.Singleton = (function() { // private members var privateAttribute = false; // private functions function privateMethod1() { ... } return { // public members publicAttribute1: true, public

【摘】JavaScript设计模式与开发实践--单例模式

本文章所有内容均摘自<Javascript设计模式与开发实践>一书(有兴趣的可以购买),加入了一点点自己的理解,写这篇文章的目的是,加强自身对设计模式的理解,以及对于没有接触过这一块的入门者的参考. 阅读本章内容,需要具备Javascript面向对象的知识,否则阅读起来可能会些许困难. 设计模式 单例模式 策略模式 代理模式 迭代器模式 发布-订阅模式 命令模式 组合模式 模板方法模式 享元模式 职责链模式 中介者模式 装饰者模式 状态模式 适配器模式 单例模式 单例模式的定义:保证一个类仅有

JavaScript设计模式 Item 6 --单例模式Singleton

单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池.全局缓存.浏览器的window对象.在js开发中,单例模式的用途同样非常广泛.试想一下,当我们单击登录按钮的时候,页面中会出现一个登录框,而这个浮窗是唯一的,无论单击多少次登录按钮,这个浮窗只会被创建一次.因此这个登录浮窗就适合用单例模式. 1.单例模式的使用场景 在使用一种模式之前,我们最好要知道,这种模式的使用场景.用了这么久的单例模式,竟全然不知!用它

【Javascript设计模式1】-单例模式

<parctical common lisp>的作者曾说,如果你需要一种模式,那一定是哪里出了问题.他所说的问题是指因为语言的天生缺陷,不得不去寻求和总结一种通用的解决方案. 不管是弱类型或强类型,静态或动态语言,命令式或说明式语言.每种语言都有天生的优缺点.一个牙买加运动员, 在短跑甚至拳击方面有一些优势,在练瑜伽上就欠缺一些. 术士和暗影牧师很容易成为一个出色的辅助,而一个背着梅肯满地图飞的敌法就会略显尴尬. 换到程序中, 静态语言里可能需要花很多功夫来实现装饰者,而js由于能随时往对象上

【javascript设计模式】构造器模式、模块模式、单例模式

构造器模式(Constructor) 构造器模式是学习js最早接触的一种,实现主要如下: 1 function myObject(name){ 2 this.name = name; 3 } 4 5 myObect.propotype = function sayName(){ 6 alert(this.name); 7 } 使用的时候需要new一个对象. 1 var myObj = new myObject('hello'); 2 myObj.sayName(); 模块模式(Module) 模

Javascript面向对象之三单例模式-《javascript设计模式》笔记

1.单例模式概述源自百度百科对于单例模式的定义:单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 在javascript的世界里,其实没有严格的对象和类定义,“一切皆对象”使得javascript中都是对象,不能像java,c++或者php使用特定的方法返回一个实例来实现,因此对javascript来说,我们要创造的是一个“不能被多次实例化的”对象,也就是说只能实例化一次的对象. 2.简单单例模式:只能实例化一次的对象也

[JavaScript设计模式]惰性单例模式

惰性单例模式 之前介绍了JS中类的单例模式,这次我们讨论下单例模式的应用.在众多网站中,登录框的实现方式就是一个单例,点击一次就展示一次,所以我们可以在页面加载好的时候就创建一个登录框,点击页面上的登录按钮时,用于控制它的显示和隐藏. 代码实现: 登录 ``` --> 这样的问题就是,如果用户进来后所有的操作根本没有用到登录,那创建登录框这个操作就是无用的,所以改进为当用户点击登录按钮时才开始创建登录框,如下: 登录 ``` --> 现在达到了惰性的目的,但失去了单例的效果.每次点击登录都会创

javascript设计模式

javascript设计模式 阅读目录 什么是设计模式 单体模式: 工厂模式: 单例模式 观察者模式(发布订阅模式) 策略模式 模板模式 代理模式 外观模式 设计模式太多了,貌似有23种,其实我们在平时的工作中没有必要特意去用什么样的设计模式,或者你在不经意间就已经用了设计模式当中的一种.本文旨在总结平时相对来说用的比较多的设计模式. 回到顶部 什么是设计模式 百度百科: 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用设计模式是