组件库项目中运用的单例模式 | 青训营笔记

111 阅读2分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 3 天

前言

单例模式:全局只允许有一个实例,多则出错

1. 主要内容

概念介绍,解决的问题

代码演示和UML类图

应用场景

1)学习方法

UML 类图要结合代码理解

设计模式要结合使用场景,否则记不住

2)注意事项

前端对单例模式并不常用,但单例的思想随处可见

2. 单例模式

一个 对象 / 实例 只能被创建一次

创建之后缓存起来,以后继续使用

即,一个系统中只有一个

1)示例

登录框,遮罩层,一个系统只有一个即可,多了无用

Vue Redux 的 store,一个系统中只能有一个,多了会出错

2)单例模式 - 演示

使用 TypeScript 演示

使用 JavaScript 演示

验证:是否符合开放封闭原则?

3)附:TypeScript 静态属性

普通属性是 实例属性 / 对象属性

static 静态属性

 class Person {
   // 实例属性
   name:string
   ...,  
   // Person 对象属性
   static flag: string = "abc"
 }
 ​
 console.log(Person.flag)  // "abc" 

4)单列模式 - TS 演示

image-20230108170901776 image-20230108170909955

5)单例模式 - JS 演示

利用闭包实现单例

 // 利用闭包实现单例
 function genGetInstance() {
   let instance;
   class SingleTon {}
   return () => {
     if (instance === null) {
       instance = new SingleTon();
     }
     return instance;
   };
 }
 // 获取返回函数
 const getInstance = genGetInstance();
 const s1 = getInstance();
 const s2 = getInstance();
 console.log(s1 === s2);
 ​

利用模块化实现单例

 // 模块化 - commonjs ES6 Module
 ​
 // getInstance.js 文件 - 开始
 let instance;
 ​
 class SingleTon {}
 ​
 export default () => {
   if (instance === null) {
     instance = new SingleTon();
   }
   return instance;
 };
 // getInstance.js 文件 - 结束

6)单例模式 - 使用场景 - 登录框

 class LoginForm {
   // 登录框业务
   state: "show" | "hide" = "hide"; // "show" / "hide"
   private constructor() {}
   hide() {
     if (this.state === "show") {
       console.log("已经显示了");
       return;
     }
     // 显示逻辑...
     this.state = "show";
   }
   show() {
     if (this.state === "hide") {
       console.log("已经隐藏了");
       return;
     }
     // 隐藏逻辑...
     this.state = "hide";
   }
 ​
   // 单例模式
   private static instance: LoginForm | null = null;
   static getInstance(): LoginForm {
     if (this.instance === null) {
       this.instance = new LoginForm();
     }
     return this.instance;
   }
 }
 ​
 const s1 = LoginForm.getInstance();
 const s2 = LoginForm.getInstance();
 console.log(s1 === s2);
 s1.hide();
 s1.hide();
 s2.show();
 ​

7)其他

自定义事件 EventBus 全局唯一

Vue Redux 的 store 全局唯一

(严格的单例模式应用不多,但单例的思想随处可见)

3. 是否符合设计原则?

内部封装 getInstance,高内聚,低耦合

4. 总结

使用 TypeScript 演示(注意 static)

使用 JavaScript 演示

验证:符合开放封闭原则

注意:Java 等多线程语言,单例要加线程锁(JS 是单线程语言)

5. 内容回顾

概念介绍,解决的问题

  • 单例解决,全局唯一对象问题

代码演示(分 TS 和 JS)和 UML 类图

应用场景:登录框

6. 重要细节

TypeScript 的 static,在 UML 中的表示(使用下划线)

TypeScript static 方法中的 this

  • static 里面的 this 是本身这个构造函数
  • public 里面的 this 是 new 出来的实例对象

Java 多线程语言,单例模式要加线程锁

7. 注意事项

前端对单例模式并不常用,但单例的思想随处可见