"每次Review同事的代码都像在拆炸弹?明明功能实现了,却总在维护时踩坑?90%的前端开发者忽略了设计模式的力量——不是模式没用,而是你用错了姿势!"
痛点共鸣
在快节奏的前端开发中,我们常陷入两大困局:
- 野蛮生长:需求倒逼下堆砌面条代码,三个月后连自己都看不懂
- 过度设计:生搬硬套Java/C++模式,反而让JavaScript失去灵活性
价值预告
本文将深度解析15种真正适配JavaScript/TypeScript基因的设计模式,每个模式都具备:
✅ 真实业务场景案例
✅ 可复用的TypeScript实现
✅ 避坑指南 + 性能权衡
正文:15大设计模式实战精解
1. 单例模式(Singleton)
痛点场景:全局状态管理(如用户认证信息)
TS实现:
class AuthService {
private static instance: AuthService;
private constructor() {} // 阻止外部实例化
public static getInstance(): AuthService {
if (!AuthService.instance) {
AuthService.instance = new AuthService();
}
return AuthService.instance;
}
// 业务方法
public login(user: string) {
console.log(`${user} logged in`);
}
}
// 使用示例
const auth1 = AuthService.getInstance();
const auth2 = AuthService.getInstance();
console.log(auth1 === auth2); // true
避坑指南:
⚠️ 避免在React/Vue组件中滥用,优先考虑Context/Provider
2. 观察者模式(Observer)
痛点场景:实时数据推送(如股票行情、聊天消息)
TS实现:
interface Observer {
update(data: any): void;
}
class StockPublisher {
private observers: Observer[] = [];
private price: number = 0;
public subscribe(observer: Observer) {
this.observers.push(observer);
}
public setPrice(newPrice: number) {
this.price = newPrice;
this.notify();
}
private notify() {
this.observers.forEach(obs => obs.update(this.price));
}
}
// 使用示例
class MobileApp implements Observer {
update(price: number) {
console.log(`[MOBILE] Price updated: $${price}`);
}
}
const publisher = new StockPublisher();
publisher.subscribe(new MobileApp());
publisher.setPrice(150); // [MOBILE] Price updated: $150
性能权衡:
🔹 适合低频更新场景
🔹 高频更新建议改用RxJS
3. 策略模式(Strategy)
痛点场景:多算法切换(如支付方式、表单校验)
TS实现:
interface ValidationStrategy {
validate(input: string): boolean;
}
class EmailValidator implements ValidationStrategy {
validate(input: string) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input);
}
}
class PhoneValidator implements ValidationStrategy {
validate(input: string) {
return /^1[3-9]\d{9}$/.test(input);
}
}
class ValidatorContext {
constructor(private strategy: ValidationStrategy) {}
setStrategy(strategy: ValidationStrategy) {
this.strategy = strategy;
}
execute(input: string) {
return this.strategy.validate(input);
}
}
// 使用示例
const context = new ValidatorContext(new EmailValidator());
console.log(context.execute("test@example.com")); // true
context.setStrategy(new PhoneValidator());
console.log(context.execute("13800138000")); // true
4. 装饰器模式(Decorator)
TS专属优势:语法级支持!
实战场景:API请求日志增强
function LogRequest(target: any, key: string, desc: PropertyDescriptor) {
const original = desc.value;
desc.value = async function (...args: any[]) {
console.log(`[REQUEST] ${key} called with:`, args);
const result = await original.apply(this, args);
console.log(`[RESPONSE] ${key} returned:`, result);
return result;
}
}
class UserService {
@LogRequest
async fetchUser(id: number) {
return { id, name: "John" };
}
}
// 使用示例
new UserService().fetchUser(1);
// 输出:
// [REQUEST] fetchUser called with: [1]
// [RESPONSE] fetchUser returned: {id:1, name:"John"}
5. 工厂模式(Factory)
痛点场景:复杂对象创建(如UI组件生成)
TS实现:
interface Button {
render(): string;
}
class PrimaryButton implements Button {
render() { return "<button class='primary'>Submit</button>"; }
}
class DangerButton implements Button {
render() { return "<button class='danger'>Delete</button>"; }
}
class ButtonFactory {
public static createButton(type: "primary" | "danger"): Button {
switch (type) {
case "primary": return new PrimaryButton();
case "danger": return new DangerButton();
default: throw new Error("Invalid button type");
}
}
}
// 使用示例
console.log(ButtonFactory.createButton("danger").render());
// <button class='danger'>Delete</button>
6. 适配器模式(Adapter)
痛点场景:整合第三方库时接口不兼容(如新旧支付SDK对接)
TS实现:
// 旧版支付宝接口
class AlipayLegacy {
createPayment(amount: number) {
return `ALIPAY:${amount}`;
}
}
// 新版微信支付接口
interface ModernPayment {
pay(amount: number): string;
}
// 适配器
class PaymentAdapter implements ModernPayment {
constructor(private legacy: AlipayLegacy) {}
pay(amount: number) {
const legacyResult = this.legacy.createPayment(amount);
return `ADAPTED: ${legacyResult.replace('ALIPAY', 'WECHAT')}`;
}
}
// 使用示例
const adapter = new PaymentAdapter(new AlipayLegacy());
console.log(adapter.pay(100)); // ADAPTED: WECHAT:100
避坑指南:
⚠️ 避免过度适配导致嵌套过深
⚠️ 优先考虑重构接口的可能性
7. 代理模式(Proxy)
痛点场景:API请求缓存/权限控制
TS实现:
interface DataService {
fetchData(): Promise<string>;
}
class RealService implements DataService {
async fetchData() {
// 模拟网络请求
await new Promise(res => setTimeout(res, 1000));
return "Real data";
}
}
class CacheProxy implements DataService {
private cache: string | null = null;
private realService = new RealService();
async fetchData() {
if (!this.cache) {
this.cache = await this.realService.fetchData();
}
return `[CACHED] ${this.cache}`;
}
}
// 使用示例
const proxy = new CacheProxy();
console.log(await proxy.fetchData()); // [CACHED] Real data (慢)
console.log(await proxy.fetchData()); // [CACHED] Real data (瞬时)
性能权衡:
🔹 适合IO密集型操作
🔹 注意缓存失效策略
8. 迭代器模式(Iterator)
痛点场景:统一遍历不同数据结构(如树形菜单/扁平列表)
TS实现:
class TreeNode<T> {
constructor(
public value: T,
public children: TreeNode<T>[] = []
) {}
}
class TreeIterator<T> {
private stack: TreeNode<T>[] = [];
constructor(root: TreeNode<T>) {
this.stack.push(root);
}
next(): T | null {
if (!this.hasNext()) return null;
const node = this.stack.pop()!;
// 反向压栈保证顺序
node.children.slice().reverse().forEach(child => {
this.stack.push(child);
});
return node.value;
}
hasNext(): boolean {
return this.stack.length > 0;
}
}
// 使用示例
const tree = new TreeNode(1, [
new TreeNode(2, [new TreeNode(4)]),
new TreeNode(3)
]);
const iterator = new TreeIterator(tree);
while (iterator.hasNext()) {
console.log(iterator.next()); // 1, 2, 4, 3
}
9. 状态模式(State)
痛点场景:复杂状态流转(如订单生命周期)
TS实现:
interface OrderState {
next(order: Order): void;
prev(order: Order): void;
}
class DraftState implements OrderState {
next(order: Order) {
order.setState(new PaidState());
}
prev() { /* 首个状态 */ }
}
class PaidState implements OrderState {
next(order: Order) {
order.setState(new ShippedState());
}
prev(order: Order) {
order.setState(new DraftState());
}
}
class ShippedState implements OrderState {
next(order: Order) {
order.setState(new CompletedState());
}
prev(order: Order) {
order.setState(new PaidState());
}
}
class Order {
private state: OrderState = new DraftState();
setState(state: OrderState) {
this.state = state;
}
proceed() {
this.state.next(this);
}
rollback() {
this.state.prev(this);
}
}
// 使用示例
const order = new Order();
order.proceed(); // Draft -> Paid
order.proceed(); // Paid -> Shipped
order.rollback(); // Shipped -> Paid
10. 模块模式(Module)
现代方案:ES Module + TypeScript类型增强
实战场景:SDK封装与类型导出
// payment.ts
interface PaymentConfig {
apiKey: string;
timeout?: number;
}
export function createPayment(config: PaymentConfig) {
let balance = 0;
return {
deposit(amount: number) {
balance += amount;
},
pay(amount: number) {
if (balance >= amount) {
balance -= amount;
return `Paid ${amount} using ${config.apiKey}`;
}
throw new Error("Insufficient balance");
}
};
}
// 使用示例
import { createPayment } from './payment';
const payment = createPayment({ apiKey: 'KEY_123' });
payment.deposit(500);
console.log(payment.pay(300)); // Paid 300 using KEY_123
11. 发布订阅模式(Pub/Sub)
爆款场景:百万级在线聊天系统
TS黑科技:类型安全事件总线
type EventMap = {
message: [string, number];
userJoin: [string];
};
class EventBus {
private listeners: { [K in keyof EventMap]?: Function[] } = {};
on<K extends keyof EventMap>(event: K, listener: (...args: EventMap[K]) => void) {
(this.listeners[event] ||= []).push(listener);
}
emit<K extends keyof EventMap>(event: K, ...args: EventMap[K]) {
this.listeners[event]?.forEach(fn => fn(...args));
}
}
// 使用示例
const bus = new EventBus();
bus.on("message", (text, timestamp) => {
console.log(`[${timestamp}] ${text}`);
});
bus.emit("message", "Hello TS!", Date.now()); // [165000000] Hello TS!
12. 职责链模式(Chain of Responsibility)
高薪必备:中间件系统(如Express/Koa)
TS实现:
interface Handler {
setNext(handler: Handler): Handler;
handle(request: string): string | null;
}
abstract class AbstractHandler implements Handler {
private nextHandler: Handler | null = null;
setNext(handler: Handler): Handler {
this.nextHandler = handler;
return handler;
}
handle(request: string): string | null {
return this.nextHandler?.handle(request) ?? null;
}
}
class AuthHandler extends AbstractHandler {
handle(request: string) {
if (request.includes("token=valid")) return super.handle(request);
return "401 Unauthorized";
}
}
class CacheHandler extends AbstractHandler {
handle(request: string) {
if (request.includes("no-cache")) return super.handle(request);
return "304 Not Modified";
}
}
// 使用示例
const chain = new AuthHandler();
chain.setNext(new CacheHandler());
console.log(chain.handle("token=valid&no-cache")); // null (通过)
console.log(chain.handle("token=invalid")); // 401 Unauthorized
13. 命令模式(Command)
跳槽神器:实现撤销/重做功能(如在线设计工具)
TS实现:
interface Command {
execute(): void;
undo(): void;
}
class Canvas {
public content: string[] = [];
addElement(element: string) {
this.content.push(element);
}
removeLast() {
this.content.pop();
}
}
class AddCommand implements Command {
constructor(
private canvas: Canvas,
private element: string
) {}
execute() {
this.canvas.addElement(this.element);
}
undo() {
this.canvas.removeLast();
}
}
class CommandHistory {
private history: Command[] = [];
execute(command: Command) {
command.execute();
this.history.push(command);
}
undo() {
const command = this.history.pop();
command?.undo();
}
}
// 使用示例
const canvas = new Canvas();
const history = new CommandHistory();
history.execute(new AddCommand(canvas, "Button"));
history.execute(new AddCommand(canvas, "Input"));
console.log(canvas.content); // ["Button", "Input"]
history.undo();
console.log(canvas.content); // ["Button"]
14. 享元模式(Flyweight)
大厂必考:万级粒子系统性能优化
TS黑科技:
type ParticleType = {
texture: string;
color: string;
};
class ParticleFactory {
private types: Record<string, ParticleType> = {};
getType(texture: string, color: string): ParticleType {
const key = `${texture}|${color}`;
if (!this.types[key]) {
console.log(`Creating new type: ${key}`);
this.types[key] = { texture, color };
}
return this.types[key];
}
}
class Particle {
constructor(
private type: ParticleType,
public x: number,
public y: number
) {}
render() {
console.log(`Rendering ${type.texture} at (${x},${y})`);
}
}
// 使用示例
const factory = new ParticleFactory();
const particles: Particle[] = [];
// 创建10000个粒子,只有2种类型
for (let i = 0; i < 5000; i++) {
particles.push(new Particle(factory.getType("star", "yellow"), Math.random(), Math.random()));
particles.push(new Particle(factory.getType("circle", "red"), Math.random(), Math.random()));
}
// 输出: "Creating new type: star|yellow" 和 "Creating new type: circle|red" 各一次
15. 模板方法模式(Template Method)
架构师思维:AI工作流引擎设计
TS实现:
abstract class AIPipeline {
// 模板方法
public run() {
this.loadData();
this.preprocess();
this.train();
this.evaluate();
this.deploy();
}
protected abstract loadData(): void;
protected abstract preprocess(): void;
protected train() {
console.log("Default training...");
}
protected evaluate() {
console.log("Default evaluation...");
}
protected deploy() {
console.log("Deploying to cloud...");
}
}
class ImagePipeline extends AIPipeline {
protected loadData() {
console.log("Loading image dataset...");
}
protected preprocess() {
console.log("Resizing images to 224x224...");
}
protected train() {
console.log("Fine-tuning ResNet50...");
}
}
// 使用示例
new ImagePipeline().run();
/* 输出:
Loading image dataset...
Resizing images to 224x224...
Fine-tuning ResNet50...
Default evaluation...
Deploying to cloud...
*/
15大设计模式终极对照表(含适用场景+实战案例)
| 设计模式 | 适用场景 | 案例1 | 案例2 | 案例3 |
|---|---|---|---|---|
| 单例模式 | 全局唯一实例需求 | 用户认证服务 | 应用配置管理器 | 日志记录器 |
| 观察者模式 | 实时数据联动更新 | 股票行情推送系统 | 表单字段联动验证 | 多人协作文档同步 |
| 策略模式 | 多算法动态切换 | 支付方式选择(微信/支付宝) | 数据校验规则库 | 地图导航路径计算 |
| 装饰器模式 | 功能动态增强 | API请求日志记录 | 用户权限校验拦截 | 性能监控埋点 |
| 工厂模式 | 复杂对象创建解耦 | UI组件库生成器 | 游戏角色生成系统 | 跨平台文件读写适配器 |
| 适配器模式 | 接口兼容转换 | 新旧支付SDK对接 | 第三方地图插件封装 | 遗留系统API现代化改造 |
| 代理模式 | 访问控制/缓存优化 | API请求缓存层 | 图片懒加载预处理器 | 敏感操作权限拦截器 |
| 迭代器模式 | 统一数据结构遍历 | 树形菜单递归遍历 | 多源数据合并查询 | 文件目录深度扫描 |
| 状态模式 | 复杂状态流转管理 | 订单生命周期管理 | 游戏角色行为状态机 | 工作流审批系统 |
| 模块模式 | 代码组织与封装 | SDK工具库开发 | 私有方法隔离实现 | 插件化架构核心 |
| 发布订阅模式 | 多对多事件通信 | 聊天室消息广播 | 微服务间事件驱动通信 | 实时数据仪表盘更新 |
| 职责链模式 | 请求流水线处理 | 中间件权限校验链 | 错误处理责任链路 | 电商优惠券规则引擎 |
| 命令模式 | 操作封装与撤销/重做 | 图形编辑器历史记录 | 智能家居遥控系统 | 自动化测试脚本执行器 |
| 享元模式 | 海量相似对象性能优化 | 粒子系统渲染优化 | 表格数据内存管理 | 游戏地图瓦片加载器 |
| 模板方法模式 | 流程标准化扩展 | AI训练流水线 | 数据导出通用框架 | 自动化部署工作流 |
深度案例解析(每个模式精选3个场景)
1. 单例模式
- 用户认证服务:全局管理登录状态,避免重复实例化
- 应用配置管理器:统一读取.env配置,线程安全
- 日志记录器:多模块共享写日志文件,防IO冲突
2. 观察者模式
- 股票行情推送:1个数据源 → 1000个客户端实时更新
- 表单字段联动:地址选择 → 自动更新快递费用计算
- 文档协同编辑:用户A编辑段落 → 用户B/C实时高亮显示
3. 策略模式
- 支付方式切换:用户选择微信 → 调用微信SDK策略
- 数据校验规则:邮箱校验 → 手机号校验 → 身份证校验
- 导航路径计算:驾车策略/步行策略/公交策略实时切换
4. 装饰器模式
- API日志增强:自动记录请求参数+响应时间+错误码
- 权限校验拦截:@AdminRequired装饰器自动验证角色
- 性能监控埋点:@Benchmark自动记录函数执行耗时
5. 工厂模式
- UI组件生成:createComponent('button', {type: 'primary'})
- 游戏角色生成:spawnEnemy('boss') vs spawnEnemy('minion')
- 文件系统适配:createFileSystem('s3') vs createFileSystem('local')
6. 适配器模式
- 支付SDK兼容:将支付宝接口适配成微信支付调用格式
- 地图插件封装:将Leaflet API转换成高德地图调用规范
- 遗留系统改造:将COBOL数据接口适配RESTful JSON格式
7. 代理模式
- API请求缓存:首次请求DB → 后续请求内存缓存
- 图片懒加载:滚动时加载真实图片 → 默认显示占位图
- 敏感操作拦截:删除操作 → 代理弹窗确认二次验证
8. 迭代器模式
- 树形菜单遍历:深度优先遍历组织架构树
- 多源数据合并:循环遍历SQL+Redis+MongoDB混合数据
- 文件目录扫描:递归遍历node_modules依赖树
9. 状态模式
- 订单状态机:draft → paid → shipped → completed
- 游戏角色行为:idle → run → attack → die状态切换
- 工作流审批:pending → approved → rejected状态流转
10. 模块模式
- SDK开发:axios.create()封装不同实例配置
- 私有方法隔离:内部实现细节隐藏,暴露简洁API
- 插件化架构:core.install(plugin)动态扩展功能
11. 发布订阅模式
- 聊天室广播:用户发言 → 所有在线成员接收消息
- 微服务通信:订单服务 → 通知库存服务扣减库存
- 实时仪表盘:数据库变更 → 大屏图表实时刷新
12. 职责链模式
- 中间件校验链:请求 → 认证 → 授权 → 限流 → 业务处理
- 错误处理链路:404错误 → 日志记录 → 邮件通知 → 降级处理
- 优惠券规则引擎:满减券 → 折扣券 → 运费券顺序应用
13. 命令模式
- 编辑器历史记录:文字操作支持50级undo/redo
- 智能家居遥控:一键执行"离家模式"(关灯+锁门+关空调)
- 自动化测试:封装click→input→assert操作为可回放命令
14. 享元模式
- 粒子系统优化:10万颗星星共享1种纹理+颜色配置
- 表格内存管理:渲染10万行数据只创建20种单元格类型
- 游戏地图加载:草原/沙漠/雪地纹理各复用1000+次
15. 模板方法模式
- AI训练流水线:数据加载 → 预处理 → 训练 → 评估标准化流程
- 数据导出框架:查询 → 格式化 → 压缩 → 上传通用模板
- 自动化部署:代码拉取 → 构建 → 测试 → 发布标准流程
设计模式避坑指南
高频陷阱与规避方案
| 设计模式 | 致命陷阱 | 规避方案 |
|---|---|---|
| 单例模式 | 内存泄漏 | 提供destroy()方法,用WeakMap存储实例 |
| 观察者模式 | 循环触发事件 | 使用异步队列(如setTimeout),添加事件ID防重 |
| 策略模式 | 策略数量爆炸 | 用配置文件动态加载策略,限制策略总数≤20 |
| 装饰器模式 | 多层嵌套性能劣化 | 限制装饰层级≤3层,复杂场景改用组合模式 |
| 代理模式 | 缓存穿透 | 添加空值缓存标记,设置缓存失效时间 |
| 发布订阅 | 消息丢失 | 引入持久化队列(如Redis),实现ACK确认机制 |
| 享元模式 | 共享状态污染 | 深拷贝共享对象,使用不可变数据结构 |
三大黄金定律
-
5行代码原则
// 坏味道:用工厂模式创建简单对象 class BadFactory { createConfig() { return { theme: 'light' } } // ❌ 过度设计 } // 优化方案 const config = { theme: 'light' }; // ✅ 直接创建 -
性能红线
模式 临界点 替代方案 装饰器链 >5层 组合函数 代理拦截 >1000次/秒 原生方法 观察者通知 >500消息/秒 批量更新机制 -
TS类型安全屏障
// 用类型体操防止模式滥用 type ForbidSingleton<T> = T extends { new(): infer U } ? "Use dependency injection instead!" : U;
结语:设计模式的终极哲学
“模式是路标,不是牢笼”
- 当你的代码需要3层注释才能解释设计模式的应用时,你已经误入歧途
- 真正的架构师能在
模式与简洁间精准取舍- 记住:删除代码比编写代码更需要勇气
资源推荐
- [TypeScript设计模式实战 - GitHub](github.com/torokmark/d…)
- 包含23个模式的完整实现
- 配套性能测试用例
- [JavaScript设计模式精髓 - 掘金小册](juejin.cn/book/684473…)
- 结合Vue/React真实案例
- 内存泄漏检测指南
- 设计模式调试工具
npx design-pattern-lint <your_file.ts>
最后忠告:
“最好的设计模式,是让你的代码在半年后还能被新手读懂——这才是真正的技术深度。”