TypeScript 设计模式
设计模式是前人总结的、针对常见问题的可复用解法。TypeScript 拥有接口、抽象类、泛型与访问修饰符,让"面向接口编程"真正落地。本节用 TS 实现四个高频模式:单例、工厂、观察者、策略。
单例模式
单例保证一个类全局只有一个实例,常用于配置中心、日志器。用 private 构造器阻止外部 new:
class Logger {
private static instance: Logger;
private constructor() {} // 禁止外部直接 new
static getInstance(): Logger {
if (!Logger.instance) Logger.instance = new Logger();
return Logger.instance;
}
log(msg: string): void {
console.log(`[LOG] ${msg}`);
}
}
Logger.getInstance().log("hello"); // 输出:[LOG] hello
Logger.getInstance().log("again"); // 输出:[LOG] again
可自行验证 Logger.getInstance() === Logger.getInstance() 为 true,两次拿到的是同一个对象。
工厂模式
工厂把"创建哪个对象"的决策集中起来,调用方只依赖抽象接口,新增产品类型时无需改动调用方:
interface Shape {
area(): number;
}
class Circle implements Shape {
constructor(private r: number) {}
area(): number { return Math.PI * this.r * this.r; }
}
class Square implements Shape {
constructor(private side: number) {}
area(): number { return this.side * this.side; }
}
function shapeFactory(kind: "circle" | "square", size: number): Shape {
return kind === "circle" ? new Circle(size) : new Square(size);
}
console.log(shapeFactory("circle", 2).area()); // 输出:12.566370614359172
console.log(shapeFactory("square", 2).area()); // 输出:4
观察者(发布订阅)模式
对象间"松耦合"通信:主题状态变化时通知所有订阅者,泛型让事件数据保持类型安全:
type Handler<T> = (data: T) => void;
class EventBus<T> {
private handlers: Handler<T>[] = [];
on(h: Handler<T>): void { this.handlers.push(h); }
emit(data: T): void { this.handlers.forEach((h) => h(data)); }
}
const bus = new EventBus<string>();
bus.on((m) => console.log("订阅者1收到:", m));
bus.on((m) => console.log("订阅者2收到:", m));
bus.emit("更新了"); // 输出:订阅者1收到: 更新了 / 订阅者2收到: 更新了
策略模式
把可替换的算法各自封装成对象,运行时自由切换,消除大量 if/else:
interface SortStrategy {
sort(data: number[]): number[];
}
const asc: SortStrategy = { sort: (d) => [...d].sort((a, b) => a - b) };
const desc: SortStrategy = { sort: (d) => [...d].sort((a, b) => b - a) };
function runSort(data: number[], s: SortStrategy): number[] {
return s.sort(data);
}
console.log(runSort([3, 1, 2], asc)); // 输出:[1, 2, 3]
console.log(runSort([3, 1, 2], desc)); // 输出:[3, 2, 1]
小结
单例管全局唯一、工厂隔离创建逻辑、观察者解耦通知、策略替换算法。TS 的接口与泛型让这些模式在编译期就被固定下来,比 JS 时代的实现更可靠、更好维护。