前端小白变形记:你要学会这些设计模式!第二弹:单例模式

前言

  1. 从这一篇开始,我会持续地更新每一种设计模式的内容,争取用通俗易懂的语言讲解和解释清楚。如果对你有帮助,请不要吝啬手中的赞~ 如果对文章内容有任何疑惑都可以在评论区提出和讨论~

  2. 本系列文章中的完整源码已上传 github 仓库,你可以在这里 FatMii/Design-Mode 获取。同样的,如果对你有帮助,请给我一个star~谢谢

  3. 设计模式合集链接:

    前端小白变形记:你要学会这些设计模式!首发:工厂模式

    前端小白变形记:你要学会这些设计模式!第二弹:单例模式

Hello~大家好,上一篇内容讲完了工厂模式,这一篇我们继续学习单例模式

什么是单例模式呢?顾名思义,就是一个类只能生成一个实例对象,并提供一个全局访问点来获取这个实例。这个模式在很多情况下都非常有用,特别是当你需要控制某些共享资源或服务的访问时,如状态管理,配置对象等。

除此之外,单例模式被广泛应用于多种框架和工具包场景,对于 Vue.js 全家桶,即 Vue.js 框架及其官方维护的周边库(如 Vuex、Vue Router等),单例模式的应用尤为明显。

前端开发中单例模式的应用场景:

  1. 状态管理(Vuex)

    • Vuex :Vuex 是 Vue 的官方状态管理库,它实现了一个集中式存储,用来存储所有组件的共享状态。这个存储是响应式的,当 Vue 组件从 store 中读取状态的时候,若状态发生变化,相应的组件也会得到高效的更新。Vuex 的 store 是一个单例,整个应用只创建一个 store 实例,确保了应用各个部分状态的一致性。
  2. 路由管理(Vue Router)

    • Vue Router :Vue Router 是 Vue 的官方路由管理器,它允许你建立单页面应用中的路由系统。在 Vue Router 中,整个应用只有一个 router 实例,这个实例在不同组件之间共享,保证了路由配置的统一性和路由状态的一致性。每次路由变化,对应的视图和组件状态会更新,这需要确保全局只有一个路由实例来控制这些更新。

单例模式的核心特点:

  • 单一实例:确保只创建一个类的实例。
  • 全局访问点:提供一个全局可访问的接口用于访问该实例。
  • 自我管理:单例类通常自己负责管理它的创建和生命周期

单例模式的缺点:

  1. 全局状态:单例模式本质上提供了一个全局状态,这可能导致代码难以测试和维护,因为系统的不同部分可能会以不可预见的方式相互影响。
  2. 违反单一职责原则:由于单例类除了自己的方法外,还负责管理自身的唯一实例,这可能会使单例类过于复杂。
  3. 扩展困难:由于单例模式的特性,扩展单例类或其子类通常比较复杂,有时可能需要修改单例实现,这可能会导致代码违背开放-封闭原则。

代码实现

javascript 复制代码
class Singleton {
  static instance;

  static getInstance() {
    if (!Singleton.instance) {
      Singleton.instance = new Singleton();
    }
    return Singleton.instance;
  }
  
  constructor() {
    if (Singleton.instance) {
      return Singleton.instance;
    }
    Singleton.instance = this;
  }

  // 示例方法
  someMethod() {
    console.log("I am doing something.");
  }
}

// 使用单例
const instance1 = new Singleton();
const instance2 = new Singleton();

instance1.someMethod(); // Output: I am doing something.

console.log(instance1 === instance2); // Output: true

在ES6中,通过使用class关键字和static静态属性,我们可以非常方便地实现单例模式。使用static关键字声明的属性或方法,如示例中的instance属性和getInstance方法,将成为类的静态属性静态方法

那么,静态属性、静态方法普通属性、普通方法有何区别呢?

关键区别在于:静态属性和方法属于类本身,而普通属性和方法则属于由类构造的实例对象。

简而言之,当你在类上定义静态成员时,这些成员可直接通过类访问,而不依赖于任何实例。这使得静态成员非常适合用作实现单例模式的工具,因为它们不会随着实例的创建而重复生成。

javascript 复制代码
console.log(Singleton.instance);      // Singleton {}
console.log(Singleton.getInstance())  // Singleton {}

console.log(instance1.instance);   // undefined,因为实例对象instance1上没有声明过普通属性instance
console.log(instance1.getInstance()); // ReferenceError: instance1 is not defined 
                                      // 静态方法调用直接在类上进行,不能在类的实例上调用。静态方法通  常用于创建实用程序函数。

关于static的更详细介绍,你可以在CDN上学习:static

ES5实现单例模式

如果没有es6中的static关键字我们想实现一个单例模式是比较繁琐的,需要借助到闭包

在JavaScript中使用闭包来实现单例模式主要是为了提供几个关键的好处,包括封装性数据隐私状态持久化。闭包允许某些数据保持私有,而对外只暴露必要的接口,这是实现单例模式的理想选择。

javascript 复制代码
var Singleton = (function() {
    // 私有变量,存储单例实例
    var instance;

    // 构造函数定义
    function Singleton() {
        if (instance) {
            return instance;
        }

        instance = this;

        // 定义一些属性和方法
        this.property = "I am a property";
        this.method = function() {
            console.log("I am a method");
        };
    }

    return Singleton;
})();

// 创建实例
var instance1 = new Singleton();
var instance2 = new Singleton();

console.log(instance1 === instance2); // 输出: true

instance1.method(); // 输出: "I am a method"

在这个实现中,Singleton构造函数内部检查是否已经存在一个实例。如果存在,它将直接返回这个实例;如果不存在,它将创建一个新的实例。这是通过在构造函数内部检查一个私有变量instance来实现的,该变量在构造函数外部通过闭包保持私有。这种方法有效地确保了类的单一实例

相关推荐
江天澄19 小时前
HTML5 中常用的语义化标签及其简要说明
前端·html·html5
知识分享小能手20 小时前
jQuery 入门学习教程,从入门到精通, jQuery在HTML5中的应用(16)
前端·javascript·学习·ui·jquery·html5·1024程序员节
美摄科技20 小时前
H5短视频SDK,赋能Web端视频创作革命
前端·音视频
七号练习生.c20 小时前
JavaScript基础入门
开发语言·javascript·ecmascript
黄毛火烧雪下20 小时前
React Native (RN)项目在web、Android和IOS上运行
android·前端·react native
fruge20 小时前
前端正则表达式实战合集:表单验证与字符串处理高频场景
前端·正则表达式
baozj20 小时前
🚀 手动改 500 个文件?不存在的!我用 AST 撸了个 Vue 国际化神器
前端·javascript·vue.js
用户40993225021220 小时前
为什么Vue 3的计算属性能解决模板臃肿、性能优化和双向同步三大痛点?
前端·ai编程·trae
海云前端120 小时前
Vue首屏加速秘籍 组件按需加载真能省一半时间
前端
蛋仔聊测试20 小时前
Playwright 中route 方法模拟测试数据(Mocking)详解
前端·python·测试