分享

单例模式

 路人甲Java 2021-08-23

单例模式

简单的单例模式

通过一个getInstance方法获取对象,首先判断一个对象是否存在,如果存在则就将改对象返回,如果不存在就先实例化对象(创建对象),然后再返回

将实例存储在对象中

let Singleton = function(name){
  this.name = name;
}

// 将实例存储在对象中
Singleton.getInstance = function() { 
  // 如果本身到
  if(this.instance === null){
    this.instance = new Singleton();
  }
  return this.instance;
}

let aIns = Singleton.getInstance("test");
let bIns = Singleton.getInstance("test");

console.log(aIns === bIns);

使用闭包存储实例对象

// 将实例使用闭包的形式存储起来
Singleton.getInstanceNew = (function() { 
  let instance = null;
  return function(){
    if(instance === null){
      instance = new Singleton();
    }
    return instance;
  } 
}())  

let cIns = Singleton.getInstanceNew("test");
let dIns = Singleton.getInstanceNew("test");

console.log(cIns === dIns, aIns === dIns);

我们看到以上两个方法,都是创建单例的简单方法,虽然实现了,但是如果别人不知道这个对象时单例的,还是可以使用new关键字创建。并且不再是单例了,所以很容易违背了我们单例的初心

透明的单例模式

我们依然通过new创建实例,但是创建的还是单例的,这样即使不需要我们特意去嘱咐这个对象是单例

var TransparentSingleton = (function() {
   var instance = null;
   var TransparentSingleton = function(){
      if(instance){
        return instance;
      }
      this.init();
      return instance = this;
   } 

   TransparentSingleton.prototype.init = function(){
    console.log("Dom操作")
  }

  return TransparentSingleton;
}())


let eIns = new TransparentSingleton();
let fIns = new TransparentSingleton();

console.log(eIns === fIns);

这种方法虽然满足了我们的要求,但是这里存在一个问题,就是内部的TransparentSingleton的这对象,成为了一个私有对象,我们在外面无法访问到

代理版单例模式

var CreateDom = function(html){
  this.html = html;
  this.init();
}

CreateDom.prototype.init = function(){
  console.log(this.html);
}

var ProxyCreateDom = (function(){
  let instance = null;
  return function(html){
    if(instance === null){
      instance = new CreateDom(html);
    }
    return instance;
  }
}())

let hIns = new ProxyCreateDom("测试");
let gIns = new ProxyCreateDom("前端");
console.log(hIns === gIns, hIns.html, gIns.html)

这里我们将对象提了出来了,通过ProxyCreateDom去创建一个关于CreateDom的单例,但是这个版本是比较有限的,我们可以看到这个代理单例并不是一个可复用的,代码很可能会翻倍。并且不管我们需不要单例,其实ProxyCreateDom里的instance就创建了。并且这个是属于传统面向对象语言的,在JavaScript这个没有类的语言中,这样创建意义并不大

惰性单例模式通用版本

let getSingleton = function(func) { 
  let result = null;
  return function(){ 
    return result || (result = func.apply(this, arguments));
  }
}

function createLoginLayer(){
  var div = document.createElement("div");
  div.innerHTML = "我是登录浮窗";
  div.style.display = "none";
  document.body.appendChild(div);
  return div;
}

/**
 * 测试代码 
 */
let createSingleLoginLayer = getSingleton(createLoginLayer); 
// 添加一个登陆浮窗
document.getElementById("loginTest").onclick = function(){
  var loginLayer = createSingleLoginLayer();
  loginLayer.style.display = "block"
}
// 创建一个iframe的单例
var createSingleIfame = getSingleton(function () {
  var iframe = document.createElement("iframe");
  document.body.appendChild(iframe);
  return iframe;
})
// 创建一个iframe,并将src属性设置为百度
document.getElementById("loginBtn").onclick = function(){
  var loginLayer = createSingleIfame();
  loginLayer.src = "http://baidu,com";
}
// 将浮窗单例隐藏
document.getElementById("closeLoginBtn").onclick = function(){
  var loginLayer = createSingleLoginLayer();
  loginLayer.style.display = "none"
}
// 改变iframe的src属性
document.getElementById("changeUrlBtn").onclick = function(){
  var loginLayer = createSingleIfame();
  loginLayer.src = "http://127.0.0.1:5500/index.html";
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多