TypeScript中的设计模式:带示例的高级水平
当基础模式(单例、工厂方法、观察者)掌握后,就到了更复杂的架构解决方案的时候了。TypeScript凭借其强大的类型系统、泛型和装饰器,为实现高级GoF模式开辟了新的可能性。在本文中,我们将分析四个关键模式:抽象工厂、建造者、责任链和策略——重点放在TypeScript特有的技巧上。
1. 带类型化产品族的抽象工厂(Abstract Factory)
“抽象工厂”模式允许创建相互关联的对象族,而无需绑定到具体类。在TypeScript中,我们可以使用接口和泛型来实现产品的严格类型化。
示例:为不同操作系统创建UI组件。
// 抽象产品interface Button { render(): void; click(): void;}
interface Checkbox { render(): void; toggle(): void;}
// Windows的具体产品class WinButton implements Button { render() { console.log('渲染Windows按钮'); } click() { console.log('点击Windows按钮'); }}
class WinCheckbox implements Checkbox { render() { console.log('渲染Windows复选框'); } toggle() { console.log('切换Windows复选框'); }}
// macOS的具体产品class MacButton implements Button { render() { console.log('渲染macOS按钮'); } click() { console.log('点击macOS按钮'); }}
class MacCheckbox implements Checkbox { render() { console.log('渲染macOS复选框'); } toggle() { console.log('切换macOS复选框'); }}
// 抽象工厂interface GUIFactory { createButton(): Button; createCheckbox(): Checkbox;}
// 具体工厂class WinFactory implements GUIFactory { createButton(): Button { return new WinButton(); } createCheckbox(): Checkbox { return new WinCheckbox(); }}
class MacFactory implements GUIFactory { createButton(): Button { return new MacButton(); } createCheckbox(): Checkbox { return new MacCheckbox(); }}
// 使用function createUI(factory: GUIFactory) { const button = factory.createButton(); const checkbox = factory.createCheckbox(); button.render(); checkbox.render();}
createUI(new WinFactory());// 渲染Windows按钮// 渲染Windows复选框高级技巧:如果工厂需要处理不同类型的产品,请使用泛型:
abstract class AbstractFactory<TProduct> { abstract createProduct(): TProduct;}
class ConcreteFactory extends AbstractFactory<Button> { createProduct(): Button { return new WinButton(); }}2. 带流畅接口和不可变性的建造者(Builder)
“建造者”模式在对象具有多个可选参数时非常有用。TypeScript允许创建类型安全的建造者,并支持方法链式调用。
示例:HTTP请求配置。
class HttpRequest { private constructor( public readonly url: string, public readonly method: 'GET' | 'POST' | 'PUT', public readonly headers: Record<string, string>, public readonly body?: string ) {}
static builder(): HttpRequestBuilder { return new HttpRequestBuilder(); }}
class HttpRequestBuilder { private url: string = ''; private method: 'GET' | 'POST' | 'PUT' = 'GET'; private headers: Record<string, string> = {}; private body?: string;
setUrl(url: string): this { this.url = url; return this; }
setMethod(method: 'GET' | 'POST' | 'PUT'): this { this.method = method; return this; }
addH