Skip to content

前端大模王

设计模式可以使代码更简洁、可维护性更高:

  • 管理对象创建 (例如:单例模式、工厂模式)。
  • 提升代码的可扩展性 (例如:策略模式、状态模式)。
  • 促进代码重用 (例如:装饰器模式、原型模式)。
  • 提升代码的可维护性 (例如:观察者模式、适配器模式)。

单例模式

全局只有唯一的实例,提供全局访问点,通常用来设计全局状态管理器、资源共享、插件系统。

JavaScript
class Singleton {
    constructor() {
        if (!Singleton.Instance) {
            Singleton.Instance = this
        }
        return Singleton.Instance // new操作符只能得到第一次创建的实例,保证实例唯一
    }
}

工厂模式

接收原材料(参数)可以生产不同的实例,既能继承工厂基类内容,又解耦了对象的创建和使用,还便于拓展新对象。

JavaScript
class VehicleFactory {
    constructor(type) {
        switch () {
            case 'car': return new Car()
            case 'bike': return new Bike()
        }
    }
}

观察者模式

一对多的依赖关系,观察者(Observer)直接订阅主题(Subject),当主题状态变化时,观察者会收到通知。

主要角色:Subject主题、ConcreteSubject具体主题、Observer观察者、ConcreteObserver具体观察者

JavaScript
class Observer {
    // 观察者通用模型
    update = (subject) => console.log('subject is updated')
}
class ConreteObserver {
    constructor(name) {
        // 具体观察者实现
        Observer.call(this)
        this.name = name
    }
}
class Subject {
    observers = [];
    attach = observer => this.observers.push(observer)
    detach = observer => this.observers = this.observers.filter(o => o !== observer)
    notify = () => this.observer.forEach(o => o.update(this))
}
class ConcreteSubject {
    constructor() {
        Subject.call(this)
    }
    this.state = null
    this.setState = (newState) => {
        this.state = newState
        this.notify()
    }
}

发布订阅

发布者(Publisher)将消息发送到消息中心(Broker),订阅者(Subscriber)从消息中心接收消息。发布者和订阅者不直接交互。

JavaScript
// EventBus.ts
class EventBus {
  private listeners: { [event: string]: Function[] } = {};
  on(event: string, callback: Function) {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(callback);
  }
  emit(event: string, ...args: any[]) {
    if (this.listeners[event]) {
      this.listeners[event].forEach(callback => callback(...args));
    }
  }
}

// UserStore.ts
class UserStore {
  constructor(private eventBus: EventBus) {
    this.eventBus.on('postAdded', this.handlePostAdded);
  }
  handlePostAdded = (post: Post) => {
    console.log('New post added:', post);
  };
}

// PostStore.ts
class PostStore {
  constructor(private eventBus: EventBus) {}
  addPost(post: Post) {
    // 添加帖子逻辑
    this.eventBus.emit('postAdded', post);
  }
}

// 使用
const eventBus = new EventBus();
const userStore = new UserStore(eventBus);
const postStore = new PostStore(eventBus);

装饰器模式

类似高阶组件,不改变原有组件功能的情况下拓展功能

JavaScript
class Soda {
    eat() {
        console.log('食用小苏打')
    }
}
function addFeatures(food) {
    food.clean = () => console.log('清洁小苏打')
}
const soda = addFeatures(Soda)
soda.clean()

策略模式

封装了算法策略应对不同的场景,分离了算法和客户端代码易于切换和拓展,且避免了ifelse的条件语句可读性差

JavaScript
class NoDiscount {
    calculate = amount => amount // 没有优惠
}
class FixedDiscount(discount) {
    calculate = amount => amount - discount // 降价优惠
}
class PercentageDiscount(rate) {
    calculate = amount => amount * rate // 打折优惠
}
class ShoppingCart {
    amount = 0
    constructor(discountStrategy) {
        this.discountStrategy = discountStrategy 
    }
    setDiscountStrategy = discountStrategy => this.discountStrategy = discountStrategy
    addAmount = cost => (this.amount += cost)
    checkout = () => {
        const finalAmount = this.discountStrategy.calculate(this.amount)
    }
}
const cart = new ShoppingCart(new NoDiscount())
cart.setDiscountStrategy(new PercentageDiscount(0.8))
cart.checkout()

状态模式

将行为与状态分离,把状态的转换封装到多个独立的类中,降低主业务逻辑复杂度,便于新增修改状态

JavaScript
class TrafficLight {
  constructor() {
    this.state = new RedState(this); // 默认红灯
  }
  setState(state) {
    this.state = state; // 修改状态
  }
  handleRequest() {
    this.state.handleRequest();
  }
}

class RedState {
  constructor(trafficLight) {
    this.trafficLight = trafficLight;
  }
  handleRequest() {
    this.trafficLight.setState(new GreenState(this.trafficLight));  // 转绿灯
  }
}
class GreenState {
  constructor(trafficLight) {
    this.trafficLight = trafficLight;
  }
  handleRequest() {
    this.trafficLight.setState(new YellowState(this.trafficLight));  // 转黄灯
  }
}
class YellowState {
  constructor(trafficLight) {
    this.trafficLight = trafficLight;
  }
  handleRequest() {
    this.trafficLight.setState(new RedState(this.trafficLight));  // 转红灯
  }
}

const trafficLight = new TrafficLight();
trafficLight.handleRequest();  // Red light: Stop
trafficLight.handleRequest();  // Green light: Go
trafficLight.handleRequest();  // Yellow light: Slow down
trafficLight.handleRequest();  // Red light: Stop

原型模式

JavaScript
function ConcretePrototype(name) {
    this.name = name;
}
ConcretePrototype.prototype = new Prototype(); // 继承自 Prototype
ConcretePrototype.prototype.constructor = ConcretePrototype;
ConcretePrototype.prototype.clone = function() {
    var clone = Object.create(this); // 浅拷贝
    return clone;
};
// 使用
const original = new ConcretePrototype('Original');
const copy = original.clone();
console.log(copy.name); // 输出: Original

适配器模式

JavaScript
class Old {
    get = data => ajax.get(data) // 旧的请求写法
}
class New {
    request = (type, data) => axios(type, type) // 新的请求写法
}
class Adapter {
    constructor(adapter) {
        this.adapter = adapter
    }
    request = (type, data) => {
        if (type === 'GET') this.adapter.get(data)
    }
}
const adapter = new Adapter(new Old())
adapter.request('GET', data) // 适配旧的请求统一用新的请求写法

依赖注入模式

TypeScript
// Container.ts
class Container {
  private instances: { [key: string]: any } = {};
  register(key: string, instance: any) {
    this.instances[key] = instance;
  }
  resolve<T>(key: string): T {
    return this.instances[key];
  }
}

// UserStore.ts
class UserStore {
  private postStore: PostStore;
  constructor(container: Container) {
    this.postStore = container.resolve<PostStore>('postStore');
  }
  getPosts() {
    return this.postStore.posts;
  }
}

// PostStore.ts
class PostStore {
  posts: Post[] = [];
}

// 使用
const container = new Container();
const postStore = new PostStore();
container.register('postStore', postStore);

const userStore = new UserStore(container);

基于 MIT 许可发布