工厂模式
什么是工厂模式
// 产品类:汽车
class Car {
private model;
private engine;
constructor(model: string, engine: string) {
this.model = model;
this.engine = engine;
}
drive() {
console.log(`Driving ${this.model} with ${this.engine} engine`);
}
}
function createCar(type: string) {
switch (type) {
case "sports":
return new Car("Sports Car", "V8");
case "sedan":
return new Car("Sedan", "V6");
default:
throw new Error("Unknown car type");
}
}
// 使用
const sportsCar = createCar("sports");
sportsCar.drive(); // Driving Sports Car with V8 engine
const sedanCar = createCar("sedan");
sedanCar.drive(); // Driving Sports Car with V8 engine
应用
JQuery的$函数
class JQuery {}
windown.$ = function() {
return new JQuery()
}
React的createElement
class Vdom {}
function createElement() {
return new Vdom()
}
单例模式
什么是单例模式
- 全局唯一的实力
- Vuex redux 的 store
- 全局唯一的弹框 dialog modal
// 产品类:汽车
class Car {
static instance: Car;
// 如果给constructor加上private, 外部就无法new了
// private constructor() {}
static createCar() {
if (!Car.instance) {
Car.instance = new Car();
}
return Car.instance;
}
}
// 使用
const car1 = Car.createCar();
const car2 = Car.createCar();
const car3 = new Car();
const car4 = new Car();
console.log(car1 === car2, car3 === car4); // true false
应用: 弹框
code
class Dialog {
static instance // 唯一实例
private overlay // 遮罩
private modal // 弹框
private content // 装文字的容器
constructor() {
this.overlay = document.createElement('div');
this.overlay.id = 'overlay';
this.modal = document.createElement('div');
this.modal.id = 'modal';
this.modal.innerHTML =
`
<div class="content"></div>
<button onclick="Dialog.instance.hide()">关闭</button>
`;
this.content = this.modal.querySelector('.content')
document.body.append(this.overlay, this.modal);
}
private show(text: string) {
Dialog.instance.content.innerHTML = text;
Dialog.instance.modal.style.display = 'block';
Dialog.instance.overlay.style.display = 'block';
}
private hide() {
if (!Dialog.instance) return;
Dialog.instance.modal.style.display = 'none';
Dialog.instance.overlay.style.display = 'none';
}
static Modal() {
if(!Dialog.instance) {
Dialog.instance = new Dialog()
}
return Dialog.instance
}
}
const modal = Dialog.Modal()
const btn = document.querySelector('#btn')
btn.addEventListener('click', () => {
modal.show('大展宏图')
})
发布订阅模式
什么是发布订阅模式
function f1() {}
function f2() {}
// 绑定
e.on('e-key1', f1)
e.on('e-key2', f2)
// 触发
e.emit('e-key1')
// 解绑
e.off('e-key1', f1)
e.off('e-key2', f2)
EventBus
type TFn = (data?: unknown) => void;
interface IEvents {
[key: string]: TFn[];
}
class EventBus {
events: IEvents = {};
on(key: string, fn: TFn) {
if(!this.events[key]) this.events[key] = []
this.events[key].push(fn);
}
emit(key: string, data?: unknown) {
(this.events[key] || []).forEach((fn) => fn(data));
}
off(key: string, fn: TFn) {
this.events[key] = this.events[key] || [];
const index = this.events[key].indexOf(fn);
if (index === -1) return;
this.events[key].splice(index, 1);
}
}
export default EventBus;
观察者模式
- 就是监听
例1
btn.addEventListener('click', () => { ... })
例2
class Subject {
constructor() {
this.observers = [];
}
subscribe(fn) {
this.observers.push(fn);
}
unsubscribe(fn) {
this.observers = this.observers.filter(obs => obs !== fn);
}
notify(data) {
this.observers.forEach(fn => fn(data));
}
}
// 使用函数作为观察者
const subject = new Subject();
subject.subscribe(data => console.log(`日志: ${data}`));
subject.subscribe(data => console.log(`警报: ${data} 发生!`));
subject.notify("温度过高");
// 输出:
// 日志: 温度过高
// 警报: 温度过高 发生!
代理模式
- 使用者不能直接访问对象, 而是访问一个代理层
- 代理层可以监听 get, set
- 如ES6 Proxy 实现vue3响应式
const o = {
a: 1,
b: 2,
}
const oo = new Proxy(o, {
get(target, key) {
console.log('读取了: ', key)
return target[key]
},
set(target, key, value) {
console.log('修改了: ', key, '->', value)
target[key] = value
return true // 赋值成功返回true, 赋值失败返回false
}
})
oo.a
oo.a = 11
装饰器模式
- AOP面向切片编程
- 应用: nestjs
type Constructor = new (...arg: any[]) => any
const name = (name: string) => (constructor: Constructor) => class extends constructor {
name = name
}
@name('tom')
class A {
}
console.log(new A()); // {name: 'tom'}