欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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(); 

通过以上方法我们就可以做到只有在使用的时候才初始化,从而达到节约资源的目的

目前对于单例模式的理解就这么多,以后有了新的理解会继续更新的,溜了溜了(~ ̄▽ ̄)~