设计模式
单例模式
单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点来访问该实例。
适用场景: 引用第三方库
、弹窗
、购物车
、全局态管理
js
// ======================
// ===== 通用单例模式 =====
// ======================
function Singleton(key, classRef) {
let instance = {};
return function (...args) {
if (!instance[key]) {
instance[key] = new classRef(...args);
}
return instance[key];
};
}
// 弹窗
class DialogClass {}
const getDialog = Singleton('dialog', DialogClass);
const d1 = getDialog();
const d2 = getDialog();
console.log(d1 === d2); // 输出: true
// 购物车
class ShoppingCartClass {}
const getCart = Singleton('shopping-cart', ShoppingCartClass);
const c1 = getCart({});
const c2 = getCart({});
console.log(c1 === c2); // 输出: true
// ==========================
// ===== SingletonClass =====
// ==========================
class SingletonClass {
constructor(arg, ...nextArgs) {
if (!SingletonClass.instance) {
// 使用类的静态属性保持单例模式的唯一性
SingletonClass.instance = this;
}
return SingletonClass.instance; // 基本类型 ?this :返回值
}
}
// 弹窗
class DialogClass {}
const d1 = new SingletonClass('dialog', DialogClass, {}); // 使用单例
const d2 = new SingletonClass('dialog', DialogClass, {}); // 使用单例
console.log(d1 === d2); // true
// 购物车
class ShoppingCartClass {}
const c1 = new SingletonClass('shopping-cart', ShoppingCartClass, {}); // 使用单例
const c2 = new SingletonClass('shopping-cart', ShoppingCartClass, {}); // 使用单例
console.log(c1 === c2); // true
// =======================
// ===== NoSingleton =====
// =======================
class NoSingleton {}
const instance3 = new NoSingleton(); // 使用单例
const instance4 = new NoSingleton(); // 使用单例
console.log(instance3 === instance4); // false
// ======================
// ===== 通用单例模式 =====
// ======================
function Singleton(key, classRef) {
let instance = {};
return function (...args) {
if (!instance[key]) {
instance[key] = new classRef(...args);
}
return instance[key];
};
}
// 弹窗
class DialogClass {}
const getDialog = Singleton('dialog', DialogClass);
const d1 = getDialog();
const d2 = getDialog();
console.log(d1 === d2); // 输出: true
// 购物车
class ShoppingCartClass {}
const getCart = Singleton('shopping-cart', ShoppingCartClass);
const c1 = getCart({});
const c2 = getCart({});
console.log(c1 === c2); // 输出: true
// ==========================
// ===== SingletonClass =====
// ==========================
class SingletonClass {
constructor(arg, ...nextArgs) {
if (!SingletonClass.instance) {
// 使用类的静态属性保持单例模式的唯一性
SingletonClass.instance = this;
}
return SingletonClass.instance; // 基本类型 ?this :返回值
}
}
// 弹窗
class DialogClass {}
const d1 = new SingletonClass('dialog', DialogClass, {}); // 使用单例
const d2 = new SingletonClass('dialog', DialogClass, {}); // 使用单例
console.log(d1 === d2); // true
// 购物车
class ShoppingCartClass {}
const c1 = new SingletonClass('shopping-cart', ShoppingCartClass, {}); // 使用单例
const c2 = new SingletonClass('shopping-cart', ShoppingCartClass, {}); // 使用单例
console.log(c1 === c2); // true
// =======================
// ===== NoSingleton =====
// =======================
class NoSingleton {}
const instance3 = new NoSingleton(); // 使用单例
const instance4 = new NoSingleton(); // 使用单例
console.log(instance3 === instance4); // false
发布订阅模式
发布-订阅模式(Publish-Subscribe Pattern):类似于观察者模式,但是发布者和订阅者之间没有直接依赖关系,它们通过一个中介(通常称为事件总线)进行通信。
js
// =============================
// ===== PublishSubscribe =====
// =============================
// 发布者:订阅者队列 订阅者添加 订阅者删除 发布给订阅者
class PublishClass {
#list = [];
subscribe(subscriber) {
this.#list.push(subscriber);
}
unsubscribe(subscriber) {
this.#list = this.#list.filter((i) => i !== subscriber);
}
publish(data) {
this.#list.forEach((subscriber) => subscriber(data));
}
}
// 订阅者:信息接收
const subscriber1 = (data) => console.log('subscriber1', data);
const subscriber2 = (data) => console.log('subscriber2', data);
// 发布订阅信息
const publisher = new PublishClass();
publisher.subscribe(subscriber1);
publisher.subscribe(subscriber2);
publisher.publish('消息1');
publisher.unsubscribe(subscriber2);
publisher.publish('消息2');
// ========================
// ===== EventEmitter =====
// ========================
// 事件的发布订阅: on once off emit
class EventEmitter {
bus = {}; // { name: [listener, ...] }
on(name, listener) {
if (this.bus[name]) {
this.bus[name].push(listener);
} else {
this.bus[name] = [listener];
}
}
off(name, listener) {
if (this.bus[name]) {
this.bus[name] = this.bus[name].filter((i) => i !== listener);
}
}
once(name, listener) {
const fn = (...args) => {
listener(...args);
this.off(name, fn);
};
this.on(name, fn);
}
trigger(name) {
if (this.bus[name]) {
this.bus[name].forEach((fn) => fn());
}
}
}
// 测试用例
const e = new EventEmitter();
e.on('click', () => console.log('click 1'));
e.on('click', () => console.log('click 2'));
e.once('click', () => console.log('click 3'));
e.trigger('click');
e.trigger('click');
// click 1
// click 2
// click 3
// click 1
// click 2
// =============================
// ===== PublishSubscribe =====
// =============================
// 发布者:订阅者队列 订阅者添加 订阅者删除 发布给订阅者
class PublishClass {
#list = [];
subscribe(subscriber) {
this.#list.push(subscriber);
}
unsubscribe(subscriber) {
this.#list = this.#list.filter((i) => i !== subscriber);
}
publish(data) {
this.#list.forEach((subscriber) => subscriber(data));
}
}
// 订阅者:信息接收
const subscriber1 = (data) => console.log('subscriber1', data);
const subscriber2 = (data) => console.log('subscriber2', data);
// 发布订阅信息
const publisher = new PublishClass();
publisher.subscribe(subscriber1);
publisher.subscribe(subscriber2);
publisher.publish('消息1');
publisher.unsubscribe(subscriber2);
publisher.publish('消息2');
// ========================
// ===== EventEmitter =====
// ========================
// 事件的发布订阅: on once off emit
class EventEmitter {
bus = {}; // { name: [listener, ...] }
on(name, listener) {
if (this.bus[name]) {
this.bus[name].push(listener);
} else {
this.bus[name] = [listener];
}
}
off(name, listener) {
if (this.bus[name]) {
this.bus[name] = this.bus[name].filter((i) => i !== listener);
}
}
once(name, listener) {
const fn = (...args) => {
listener(...args);
this.off(name, fn);
};
this.on(name, fn);
}
trigger(name) {
if (this.bus[name]) {
this.bus[name].forEach((fn) => fn());
}
}
}
// 测试用例
const e = new EventEmitter();
e.on('click', () => console.log('click 1'));
e.on('click', () => console.log('click 2'));
e.once('click', () => console.log('click 3'));
e.trigger('click');
e.trigger('click');
// click 1
// click 2
// click 3
// click 1
// click 2
工厂模式
工厂模式(Factory Pattern):通过使用工厂方法来创建对象,而不是直接使用 new 关键字来创建。
构造函数模式
构造函数模式(Constructor Pattern):使用构造函数来创建对象,并通过原型链来共享方法和属性。
观察者模式
观察者模式(Observer Pattern):定义了对象之间的一对多依赖关系,当一个对象的状态发生变化时,它的所有依赖对象都将收到通知。
原型模式
原型模式(Prototype Pattern):通过克隆现有对象来创建新对象,而不是使用 new 关键字。
适配器模式
适配器模式(Adapter Pattern):将一个类的接口转换成客户端所期望的另一个接口,以解决接口不兼容的问题。
装饰者模式
装饰者模式(Decorator Pattern):动态地给对象添加额外的职责,同时又不改变其接口。
策略模式
策略模式(Strategy Pattern):定义一系列算法,并使它们可以相互替换,从而使算法的变化独立于使用它们的客户端。
代理模式
代理模式(Proxy Pattern):为其他对象提供一个代理,以控制对这个对象的访问。