Skip to content

常用设计模式

单例模式

全局只有一个对象实例,数据共享,节约资源。

在 JavaScript 中,单例模式是一种常用的设计模式,它用于保证一个类只有一个实例,并提供了一个全局访问该实例的方法。在实际开发中,单例模式通常用于管理全局状态,避免多个实例之间的数据冲突。

JavaScript 中实现单例模式有多种方式,其中最常见的方式是使用对象字面量立即执行函数表达式(IIFE)class的static关键字 来创建单例对象。具体来说,可以通过如下的方式实现单例模式:

  1. 对象字面量方式
js
const singleton = {
  instance: null,
  getInstance() {
    if (!this.instance) {
      this.instance = {
        // 单例对象的属性和方法
      };
    }
    return this.instance;
  }
};

使用时,我们可以通过调用 singleton.getInstance() 方法来获取单例对象。

  1. 立即执行函数表达式(IIFE)方式
js
const Singleton = (() => {
  let instance = null;
  return {
    getInstance() {
      if (!instance) {
        instance = {
          // 单例对象的属性和方法
        };
      }
      return instance;
    }
  };
})();
  1. 使用 ES6 的 class 和 static 关键字来实现单例模式。
js
class Singleton {
  static instance = null;

  constructor() {
    // 如果已经存在单例实例,则直接返回该实例
    if (Singleton.instance) {
      return Singleton.instance;
    }
    // 否则创建单例实例,并保存到静态属性中
    Singleton.instance = this;
    // 单例对象的属性和方法
  }

  // 获取单例对象的静态方法
  static getInstance() {
    if (!Singleton.instance) {
      Singleton.instance = new Singleton();
    }
    return Singleton.instance;
  }
}

使用时,我们可以通过调用 Singleton.getInstance() 方法来获取单例对象。

这种方式相比于之前提到的使用对象字面量或者立即执行函数表达式(IIFE)方式实现单例模式,更加符合面向对象的编程思想。同时,ES6 的 class 语法也更加易读易懂,更符合现代 JavaScript 的语言特性。

装饰器模式

对同一操作逻辑进行功能增强,比如“报名-->付费+报名”。

在 JavaScript 中,装饰器模式是一种结构性模式,它可以在不修改对象自身的基础上,动态地给对象添加一些额外的职责和功能。

装饰器模式是通过对对象进行包装来实现的,包装对象可以在运行时动态地添加、修改或删除对象的行为。在 JavaScript 中,装饰器模式通常是通过函数来实现的。

js
// 定义一个普通的对象
const obj = {
  value: 10,
  getValue() {
    return this.value;
  }
};

// 定义一个装饰器函数,用于给对象添加一个乘法器
function multiplyDecorator(obj) {
  obj.multiply = function(factor) {
    this.value *= factor;
  };
  return obj;
}

// 使用装饰器语法将 multiplyDecorator 装饰器应用于 obj 对象上
const decoratedObj = multiplyDecorator(obj);

// 调用 decoratedObj 对象的 multiply 方法
decoratedObj.multiply(2);

// 输出 decoratedObj 对象的值
console.log(decoratedObj.getValue()); // 输出: 20

工厂模式

https://zhuanlan.zhihu.com/p/474296206

观察者模式

js
// 1.被观察者
let Observer = function () {
  this.observerList = [];
};

Observer.prototype.add = function (dep) {
  this.observerList.push(dep);
};

Observer.prototype.remove = function (dep) {
  this.observerList.pop(dep);
};

Observer.prototype.notify = function () {
  this.observerList.forEach((dep) => {
    dep.update();
  });
};

// 2.观察者
let myWatcher = function (name) {
  this.name = name;
};

myWatcher.prototype.update = function () {
  console.log("%s updated", this.name);
};

let ob = new Observer();
ob.add(new myWatcher("mywatcher1"));
ob.add(new myWatcher("mywatcher2"));

// 变化后通知观察者
ob.notify();

订阅-发布模式

事件发布者和订阅者解耦,通过 消息代理(Message Broker)来进行通信 统一调度。如:文件上传进度的异步操作通知。

发布订阅模式(Publish/Subscribe Pattern)中,发布者和订阅者之间不直接通信,而是通过一个消息代理(Message Broker)来进行通信。发布者将消息发送给消息代理,订阅者向消息代理订阅感兴趣的消息,当消息代理收到发布者的消息时,会将消息分发给所有订阅者。发布订阅模式的核心是消息代理和订阅者,消息代理维护了一个订阅者列表,可以添加或删除订阅者,当收到消息时,会将消息分发给所有的订阅者。

js
-发布订阅模式-                                 
// 消息代理
class MessageBroker {
  constructor() {
    this.subscribers = {};
  }

  subscribe(event, callback) {
    if (!this.subscribers[event]) {
      this.subscribers[event] = [];
    }
    this.subscribers[event].push(callback);
  }

  unsubscribe(event, callback) {
    if (this.subscribers[event]) {
      this.subscribers[event] = this.subscribers[event].filter(cb => cb !== callback);
    }
  }

  publish(event, data) {
    if (this.subscribers[event]) {
      this.subscribers[event].forEach(cb => cb(data));
    }
  }
}

// 订阅者
class Subscriber {
  constructor(name) {
    this.name = name;
  }

  handleEvent(data) {
    console.log(`${this.name} received event data: ${data}`);
  }
}

// 使用发布订阅模式实现组件之间的通信
const broker = new MessageBroker();
const subscriber1 = new Subscriber('Subscriber 1');
const subscriber2 = new Subscriber('Subscriber 2');

broker.subscribe('event', subscriber1.handleEvent.bind(subscriber1));
broker.subscribe('event', subscriber2.handleEvent.bind(subscriber2));

broker.publish('event', 'Hello world!'); // 输出:Subscriber 1 received event data: Hello world!,Subscriber 2 received event data: Hello world!

else

Released under the MIT License.