前端设计模式-单例模式

188 阅读3分钟

前言

提示:以下是本篇文章正文内容,下面案例可供参考

单例模式的含义

  • 1、单例类只能有一个实例。
  • 2、单例类必须自己创建自己的唯一实例。
  • 3、单例类必须给所有其他对象提供这一实例。 保证一个类仅有一个实例,并提供一个访问它的全局访问点。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

生活中的单例模式

例如:

  • 1、一个班级只有一个班主任。
  • 2、一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。
  • 3、 一个人只有一个老婆。。。。。。

应用场景

  • 1、要求生产唯一序列号。
  • 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
  • 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

前端中的应用场景

    1. 登录框的显示隐藏,不同组件页面,用到同一个类的实例
    1. 购物车的功能,
    1. jQuery 里面的 $只有一个
    1. vuex 和redux状态管理的 store

实现一个单例类

实现步骤

  • 1、 创建一个 Singleton类
  • 2、 获取实例的静态方法getInstance()
  • 3、 判断是否有实例,有就返回,没有创建一个实例
  • 4、 在立即调用函数IIFE里面返回,所以只生成一次, 用TypeScript写的话就时private private static SingleObject instance = new SingleObject(); //让构造函数为 private,这样该类就不会被实例化 private SingleObject(){} //获取唯一可用的对象
class Singleton  {
  login() {
    console.log('登录一下');
  }
  // 使用static 说明的方法 直接用类名调用, 就不用new一个实例对象来调用
  // static getInstance = (function(){
  //   let instance;
  //   return function () {
  //     if(instance == null) {
  //       instance = new Singleton();
  //     }
  //     return instance;
  //   }
  // })()
}

Singleton.getInstance = (function(){
  let instance;
  return function () {
    if(instance == null) {
      instance = new Singleton();
    }
    return instance;
  }
})()

let obj1 = Singleton.getInstance()
obj1.login()
let obj2 = Singleton.getInstance()
obj2.login()
console.log('obj1 是否全等于obj2', obj1 === obj2);

console.log('----------看看通过new 实例对象的方法 出来的对象是不是等-------');
let obj3 = new Singleton()
let obj4 = new Singleton()
console.log('obj3 是否全等于obj4', obj3 === obj4);

输出情况

登录一下
登录一下
obj1 是否全等于obj2 true
----------看看通过new 实例对象的方法 出来的对象是不是等-------
obj3 是否全等于obj4 false

单例模式模拟登录框场景

class LoginForm {

  constructor() {
    this.state = 'hide'
  }

  static getInstance = (function(){
    let instance;
    return function() {
      if (!instance) {
        instance = new LoginForm()
      }
      return instance
    }
  })()

  show() {
    if (this.state === 'show') {
      console.log('显示!!!');
      return
    }
    this.state = 'show'
    console.log('登录框已经显示');
  }

  hide() {
    if (this.state === 'hide') {
      console.log('隐藏!!!');
      return
    }
    this.state = 'hide'
    console.log('登录框已经隐藏');
  }
}

let login_1 = LoginForm.getInstance()
let login_2 =  LoginForm.getInstance()

login_1.show()
login_2.hide()

console.log('login_1===login_2', login_1===login_2);

输出情况

登录框已经显示
登录框已经隐藏
login_1===login_2 true

用Java实现的单例模式种类比较多,JavaScript由于是动态类型的语言就比较限制。

看看Java中的单例模式的加强版

如:懒汉式,线程安全

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述: 这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。\

代码

public class Singleton {
    private static Singleton instance; 
    private Singleton (){} 
    public static synchronized Singleton getInstance() { 
        if (instance == null) { 
            instance = new Singleton(); 
        } 
        return instance; 
    }
}

学习地址