前端常见的设计模式之【单例模式】

前端常见的设计模式:

  1. 单例模式
  2. 观察者模式
  3. 工厂模式
  4. 适配器模式
  5. 装饰器模式
  6. 命令模式
  7. 迭代器模式
  8. 组合模式
  9. 策略模式
  10. 发布订阅模式

单例模式【创建型设计模式】:

  • 单例模式是确保一个类只有一个实例,并提供一个全局访问点
  • 这个模式非常适合那些需要共享资源的场景。常用于全局状态管理、全局配置对象,如Redux或Vuex的store,或者全局的弹窗、日志服务等。

类是什么?

  • 类是面向对象编程中的一个基本概念,它是对具有相同属性和方法的一组对象的抽象描述
  • 类定义了对象的属性(数据)和行为(方法或函数)。
  • ES6之后,JavaScript引入了**class 关键字**,使得类的定义更加直观和简洁。

实例是什么?

  • 实例是根据类创建的具体对象
  • 每个实例都有自己的属性值和可以调用的方法,但它们共享类定义的行为和结构。

类中有很多实例的代码示例:

javascript 复制代码
class NonSingleton {
  constructor(name) {
    this.name = name;
  }
}

const obj1 = new NonSingleton('Alice');
const obj2 = new NonSingleton('Bob');

obj1.name; // 'Alice'
obj2.name; // 'Bob'
// obj1 和 obj2 是两个独立的实例,更改一个不会影响另一个

类中只有一个实例的代码示例(单例模式):

在单例模式中,无论你尝试创建多少次实例,都会得到同一个对象。因此,如果你更改了这个对象的某个属性,所有引用这个对象的地方都会感知到这个更改。

javascript 复制代码
class Singleton {
  constructor() {
    if (Singleton.instance) {
      return Singleton.instance;
    }
    this.name = 'Default Name';
    Singleton.instance = this;
  }
}

const singleton1 = new Singleton();
const singleton2 = new Singleton();

singleton1.name = 'Changed Name';

singleton1.name; // 'Changed Name'
singleton2.name; // 也是 'Changed Name',因为它们引用的是同一个实例
javascript 复制代码
class Singleton {
  constructor(name) {
    // 如果实例已经存在,则直接返回它,忽略传入的参数
    if (Singleton.instance) {
      return Singleton.instance;
    }

    // 否则,使用传入的参数初始化实例
    this.name = name || 'Default Name';

    // 将当前实例存储为类的静态属性
    Singleton.instance = this;
  }

  // 静态方法用于获取实例(可选)
  static getInstance(name) {
    if (!Singleton.instance) {
      new Singleton(name);
    }
    return Singleton.instance;
  }
}

// 首次创建实例并传入参数
const singleton1 = new Singleton('Alice');
console.log(singleton1.name); // 输出: Alice

// 尝试再次创建实例,但传入不同的参数
const singleton2 = Singleton.getInstance('Bob');
console.log(singleton2.name); // 输出: Alice,因为实例已经存在,所以参数被忽略

// 验证两个引用是否指向同一个实例
console.log(singleton1 === singleton2); // 输出: true

单例模式的实现方式:

  1. 饿汉式‌:在类加载时就初始化实例,因此线程安全。优点是实现简单、线程安全;缺点是类加载时就实例化,可能造成资源浪费。
  2. 懒汉式‌:在第一次使用时才初始化实例,不是线程安全的,需要加锁。优点是延迟加载、节省资源;缺点是需要加锁、性能较差。
  3. 双重校验锁‌:在懒汉式的基础上进行了优化,减少了不必要的同步开销。优点是延迟加载、节省资源、线程安全、性能较高;缺点是代码较复杂。
  4. 静态内部类‌:利用静态内部类的特性实现单例模式,线程安全且延迟加载。优点是延迟加载、节省资源、线程安全、利用类加载机制保证初始化时只有一个线程;缺点是代码较简单、易读性好。‌
  5. 枚举‌:利用枚举实现单例模式,天生线程安全,防止反序列化创建新实例。优点是实现简单、防止反射和序列化破坏单例;缺点是不能延迟加载。

Vue单例模式示例:

在Vue中,单例模式通常不是直接应用于Vue组件本身的,因为Vue组件的实例是由Vue框架自己管理的。但是,我们可以在Vue应用中使用单例模式来管理某些全局状态或服务。例如,我们可以创建一个全局的事件总线(Event Bus)或者一个全局的配置管理器。

  1. 首先,我们定义一个单例模式的配置管理器:
javascript 复制代码
// ConfigManager.js
const ConfigManager = (function() {
  let instance;

  // 构造函数,包含一些配置信息
  function Config() {
    this.apiKey = 'your-api-key';
    this.featureFlag = true;
    // 其他配置...
  }

  // 获取单例对象的方法,检查instance变量是否已经被初始化
  function getInstance() {
    if (!instance) {
      instance = new Config();
    }
    return instance;
  }

  // 公开getInstance方法,其他方法或属性可以根据需要添加
  return {
    getInstance: getInstance
  };
})();

export default ConfigManager;
  1. 接下来,我们在Vue组件中使用这个配置管理器:
javascript 复制代码
// SomeComponent.vue
<template>
  <div>
    API Key: {{ apiKey }}
    <button @click="toggleFeature">Toggle Feature Flag</button>
  </div>
</template>

<script>
import ConfigManager from './ConfigManager';

export default {
  data() {
    return {
      apiKey: '',
      featureFlag: false
    };
  },
  created() {
    const config = ConfigManager.getInstance();
    this.apiKey = config.apiKey;
    this.featureFlag = config.featureFlag;
  },
  methods: {
    toggleFeature() {
      const config = ConfigManager.getInstance();
      config.featureFlag = !config.featureFlag;
      this.featureFlag = config.featureFlag;
    }
  }
};
</script>
相关推荐
To_OC2 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
vipbic3 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy3 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志3 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble4 小时前
c端系统,其实更像一个信息展示平台
前端
李姆斯5 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜6 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司6 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能
江华森7 小时前
Web 开发基础:HTTP 与 REST
前端·网络协议·http
IT_陈寒7 小时前
Redis的KEYS命令把我搞崩溃了,改用SCAN才活过来
前端·人工智能·后端