当前位置: 首页 > article >正文

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

前端常见的设计模式:

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

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

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

类是什么?

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

实例是什么?

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

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

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 是两个独立的实例,更改一个不会影响另一个

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

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

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',因为它们引用的是同一个实例
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. 首先,我们定义一个单例模式的配置管理器:
// 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组件中使用这个配置管理器:
// 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>

http://www.kler.cn/a/506323.html

相关文章:

  • 【Git版本控制器--1】Git的基本操作--本地仓库
  • 【C#深度学习之路】如何使用C#实现Yolo8/11 Segment 全尺寸模型的训练和推理
  • 一次完整的tcpdump -XX输出报文详解
  • 编译pytorch——cuda-toolkit-nvcc
  • 机器学习06-正则化
  • SpeingMVC框架(三)
  • 【机器学习:二十三、迁移学习】
  • 冯·诺依曼体系结构:计算机科学的奠基石
  • linux、华为modelarts、昇腾服务器、docker中,服务进程还在,但是不在运行状态,没有响应
  • 133、sqlserver查看哪个表被锁表了以及解锁方法
  • MIAOYUN信创云原生项目亮相西部“中试”生态对接活动
  • uniapp省市区懒加载封装
  • 【Linux】12.Linux进程概念(1)
  • products页面出现多选框后,能够直接将勾选的products删除吗?而不用跳转到flow再删除。例如将勾选的products传给flow
  • vmware虚拟机配置ubuntu 18.04(20.04)静态IP地址
  • 如何利用AI进行用户体验测试
  • 中职网络建设与运维ansible服务
  • jsx语法中el-table-v2中cellRender如何使用动态绑定
  • GaussDB中的Vacuum和Analyze
  • 3D打印汽车零部件
  • 【蓝桥杯嵌入式】串口空闲中断+DMA接收不定长数据
  • Swift语言的数据库编程
  • 【大语言模型】ACL2024论文-37 交互式文本到图像检索与大型语言模型:一种即插即用的方法
  • LeetCode 916. Word Subsets
  • pnpm add 和 pnpm install 的区别?
  • EE213 Lab virtuoso final project SRAM designlayout