Skip to content

设计模式

单例模式

单例模式(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):为其他对象提供一个代理,以控制对这个对象的访问。

༼ つ/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿◕ _◕ ༽つ/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿ ̿̿