前端设计模式实战:打造可维护的代码架构
前端设计模式实战:打造可维护的代码架构
前言
大家好,我是前端老炮儿。今天咱们来聊聊前端设计模式!
设计模式是软件设计中的经典解决方案,掌握设计模式可以让我们写出更优雅、更可维护的代码。但是很多同学学了设计模式却不知道怎么在实际项目中应用。
今天我就带大家一起实战前端设计模式,看看如何在真实项目中使用它们!
什么是设计模式
设计模式是一套被反复使用、经过分类编目的代码设计经验总结。它可以帮助我们:
- 提高代码可复用性
- 增强代码可维护性
- 提升系统稳定性
- 便于团队协作
前端常用设计模式
1. 单例模式 (Singleton)
确保一个类只有一个实例,并提供全局访问点。
场景:全局状态管理、配置管理、工具类
class Singleton { private static instance: Singleton | null = null private constructor() {} public static getInstance(): Singleton { if (!Singleton.instance) { Singleton.instance = new Singleton() } return Singleton.instance } public doSomething(): void { console.log('Doing something...') } } const instance1 = Singleton.getInstance() const instance2 = Singleton.getInstance() console.log(instance1 === instance2) // trueReact中应用:
class AppState { private static instance: AppState | null = null private state: Record<string, any> = {} private constructor() {} public static getInstance(): AppState { if (!AppState.instance) { AppState.instance = new AppState() } return AppState.instance } public set(key: string, value: any): void { this.state[key] = value } public get(key: string): any { return this.state[key] } }2. 工厂模式 (Factory)
定义一个创建对象的接口,让子类决定实例化哪个类。
场景:组件创建、服务初始化、数据解析
interface Product { name: string price: number } class ConcreteProductA implements Product { name = 'Product A' price = 100 } class ConcreteProductB implements Product { name = 'Product B' price = 200 } class ProductFactory { public static create(type: 'A' | 'B'): Product { switch (type) { case 'A': return new ConcreteProductA() case 'B': return new ConcreteProductB() default: throw new Error(`Unknown product type: ${type}`) } } } const productA = ProductFactory.create('A') const productB = ProductFactory.create('B')React中应用:
interface ComponentProps { type: 'button' | 'input' | 'select' } class ButtonComponent implements React.FC { render() { return <button>Click me</button> } } class InputComponent implements React.FC { render() { return <input type="text" /> } } class ComponentFactory { public static create(type: string): React.FC { switch (type) { case 'button': return ButtonComponent case 'input': return InputComponent default: throw new Error(`Unknown component type: ${type}`) } } }3. 观察者模式 (Observer)
定义对象间的一对多依赖,当一个对象状态改变时,所有依赖它的对象都会收到通知。
场景:事件系统、状态管理、发布订阅
interface Observer { update(data: any): void } class Subject { private observers: Observer[] = [] public attach(observer: Observer): void { this.observers.push(observer) } public detach(observer: Observer): void { const index = this.observers.indexOf(observer) if (index > -1) { this.observers.splice(index, 1) } } public notify(data: any): void { this.observers.forEach(observer => observer.update(data)) } } class ConcreteObserver implements Observer { private name: string constructor(name: string) { this.name = name } public update(data: any): void { console.log(`${this.name} received: ${data}`) } } const subject = new Subject() const observer1 = new ConcreteObserver('Observer 1') const observer2 = new ConcreteObserver('Observer 2') subject.attach(observer1) subject.attach(observer2) subject.notify('Hello World')4. 策略模式 (Strategy)
定义一系列算法,把它们封装起来,并且使它们可以相互替换。
场景:表单验证、排序算法、支付方式
interface Strategy { execute(data: number[]): number[] } class BubbleSort implements Strategy { execute(data: number[]): number[] { const arr = [...data] for (let i = 0; i < arr.length; i++) { for (let j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]] } } } return arr } } class QuickSort implements Strategy { execute(data: number[]): number[] { if (data.length <= 1) return data const pivot = data[Math.floor(data.length / 2)] const left = data.filter(x => x < pivot) const middle = data.filter(x => x === pivot) const right = data.filter(x => x > pivot) return [...this.execute(left), ...middle, ...this.execute(right)] } } class Context { private strategy: Strategy constructor(strategy: Strategy) { this.strategy = strategy } public setStrategy(strategy: Strategy): void { this.strategy = strategy } public executeStrategy(data: number[]): number[] { return this.strategy.execute(data) } } const data = [3, 1, 4, 1, 5, 9, 2, 6] const context = new Context(new BubbleSort()) console.log(context.executeStrategy(data)) context.setStrategy(new QuickSort()) console.log(context.executeStrategy(data))5. 装饰器模式 (Decorator)
动态地给对象添加额外的职责。
场景:权限控制、日志记录、性能监控
interface Component { operation(): string } class ConcreteComponent implements Component { operation(): string { return 'ConcreteComponent' } } class Decorator implements Component { protected component: Component constructor(component: Component) { this.component = component } operation(): string { return this.component.operation() } } class ConcreteDecoratorA extends Decorator { operation(): string { return `DecoratorA(${super.operation()})` } } class ConcreteDecoratorB extends Decorator { operation(): string { return `DecoratorB(${super.operation()})` } } const component = new ConcreteComponent() const decoratedA = new ConcreteDecoratorA(component) const decoratedB = new ConcreteDecoratorB(decoratedA) console.log(decoratedB.operation()) // DecoratorB(DecoratorA(ConcreteComponent))实战案例
案例1:状态管理系统
interface State { handle(context: Context): void } class Context { private state: State constructor(state: State) { this.transitionTo(state) } public transitionTo(state: State): void { this.state = state this.state.handle(this) } public request1(): void { this.state.handle(this) } } class ConcreteStateA implements State { handle(context: Context): void { console.log('Handling request in State A') context.transitionTo(new ConcreteStateB()) } } class ConcreteStateB implements State { handle(context: Context): void { console.log('Handling request in State B') context.transitionTo(new ConcreteStateA()) } } const context = new Context(new ConcreteStateA()) context.request1() // Handling request in State A context.request1() // Handling request in State B context.request1() // Handling request in State A案例2:组件渲染器
interface Renderer { render(): string } class HtmlRenderer implements Renderer { render(): string { return '<div>HTML Content</div>' } } class MarkdownRenderer implements Renderer { render(): string { return '# Markdown Content' } } class Document { private renderer: Renderer constructor(renderer: Renderer) { this.renderer = renderer } public setRenderer(renderer: Renderer): void { this.renderer = renderer } public render(): string { return this.renderer.render() } } const document = new Document(new HtmlRenderer()) console.log(document.render()) // <div>HTML Content</div> document.setRenderer(new MarkdownRenderer()) console.log(document.render()) // # Markdown Content设计模式选择指南
| 场景 | 推荐模式 |
|---|---|
| 全局状态管理 | 单例模式 |
| 对象创建 | 工厂模式 |
| 事件通知 | 观察者模式 |
| 算法切换 | 策略模式 |
| 功能增强 | 装饰器模式 |
| 状态切换 | 状态模式 |
| 对象组合 | 组合模式 |
| 接口适配 | 适配器模式 |
最佳实践
1. 不要过度设计
设计模式是工具,不是银弹。不要为了使用模式而使用模式。
2. 遵循SOLID原则
- Single Responsibility:单一职责
- Open/Closed:开闭原则
- Liskov Substitution:里氏替换
- Interface Segregation:接口隔离
- Dependency Inversion:依赖倒置
3. 结合框架特性
React的Hooks、Vue的Composition API都有自己的模式,要学会结合使用。
4. 保持代码简洁
设计模式的目的是让代码更清晰,而不是更复杂。
总结
通过今天的学习,我们了解了:
- 单例模式:确保唯一实例
- 工厂模式:封装对象创建
- 观察者模式:实现发布订阅
- 策略模式:动态切换算法
- 装饰器模式:动态增强功能
设计模式是程序员的内功心法,掌握它们可以让我们写出更优雅、更可维护的代码。但是记住,设计模式不是教条,要灵活运用!
最后,给大家留个思考题:在你的项目中,哪些地方可以应用设计模式来改进代码?欢迎在评论区留言讨论!
