前端大模王
设计模式可以使代码更简洁、可维护性更高:
- 管理对象创建 (例如:单例模式、工厂模式)。
- 提升代码的可扩展性 (例如:策略模式、状态模式)。
- 促进代码重用 (例如:装饰器模式、原型模式)。
- 提升代码的可维护性 (例如:观察者模式、适配器模式)。
单例模式
全局只有唯一的实例,提供全局访问点,通常用来设计全局状态管理器、资源共享、插件系统。
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);