TypeScript高级设计模式实战
•编程技术
TypeScript高级设计模式实战
TypeScript作为JavaScript的超集,不仅提供了类型系统,还支持许多面向对象的高级特性。本文将深入探讨TypeScript中的高级设计模式及其实际应用。
装饰器模式
类装饰器
function Logger<T extends { new (...args: any[]): {} }>(constructor: T) {
return class extends constructor {
constructor(...args: any[]) {
super(...args);
console.log(`Instance created: ${constructor.name}`);
}
};
}
@Logger
class UserService {
constructor(private name: string) {}
}
const user = new UserService('John'); // 输出: Instance created: UserService
方法装饰器
function MeasureTime(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const start = performance.now();
const result = await originalMethod.apply(this, args);
const end = performance.now();
console.log(`${propertyKey} took ${end - start} milliseconds`);
return result;
};
return descriptor;
}
class DataService {
@MeasureTime
async fetchData() {
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 1000));
return { data: 'result' };
}
}
依赖注入
实现简单的DI容器
interface Constructor<T> {
new (...args: any[]): T;
}
class Container {
private services = new Map<string, any>();
private singletons = new Map<string, any>();
register<T>(token: string, constructor: Constructor<T>): void {
this.services.set(token, constructor);
}
registerSingleton<T>(token: string, constructor: Constructor<T>): void {
this.services.set(token, constructor);
this.singletons.set(token, null);
}
resolve<T>(token: string): T {
const constructor = this.services.get(token);
if (!constructor) {
throw new Error(`Service ${token} not found`);
}
if (this.singletons.has(token)) {
if (!this.singletons.get(token)) {
this.singletons.set(token, new constructor());
}
return this.singletons.get(token);
}
return new constructor();
}
}
// 使用示例
interface IDatabase {
query(sql: string): Promise<any[]>;
}
class MySQLDatabase implements IDatabase {
async query(sql: string): Promise<any[]> {
console.log(`Executing: ${sql}`);
return [];
}
}
class UserRepository {
constructor(private db: IDatabase) {}
async getUsers() {
return this.db.query('SELECT * FROM users');
}
}
const container = new Container();
container.registerSingleton('database', MySQLDatabase);
container.register('userRepository', UserRepository);
工厂模式
抽象工厂
interface Button {
render(): void;
onClick(callback: () => void): void;
}
interface Checkbox {
render(): void;
toggle(): void;
}
interface UIFactory {
createButton(): Button;
createCheckbox(): Checkbox;
}
class WindowsButton implements Button {
render() {
console.log('Rendering Windows button');
}
onClick(callback: () => void) {
console.log('Windows button clicked');
callback();
}
}
class WindowsCheckbox implements Checkbox {
render() {
console.log('Rendering Windows checkbox');
}
toggle() {
console.log('Windows checkbox toggled');
}
}
class MacButton implements Button {
render() {
console.log('Rendering Mac button');
}
onClick(callback: () => void) {
console.log('Mac button clicked');
callback();
}
}
class MacCheckbox implements Checkbox {
render() {
console.log('Rendering Mac checkbox');
}
toggle() {
console.log('Mac checkbox toggled');
}
}
class WindowsUIFactory implements UIFactory {
createButton(): Button {
return new WindowsButton();
}
createCheckbox(): Checkbox {
return new WindowsCheckbox();
}
}
class MacUIFactory implements UIFactory {
createButton(): Button {
return new MacButton();
}
createCheckbox(): Checkbox {
return new MacCheckbox();
}
}
// 使用工厂
function createUI(os: 'windows' | 'mac'): UIFactory {
switch (os) {
case 'windows':
return new WindowsUIFactory();
case 'mac':
return new MacUIFactory();
default:
throw new Error('Unsupported OS');
}
}
观察者模式
类型安全的EventEmitter
type EventMap = {
[key: string]: (...args: any[]) => void;
};
class TypedEventEmitter<Events extends EventMap> {
private listeners: { [K in keyof Events]?: Events[K][] } = {};
on<K extends keyof Events>(
event: K,
listener: Events[K]
): () => void {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event]!.push(listener);
return () => this.off(event, listener);
}
off<K extends keyof Events>(event: K, listener: Events[K]): void {
if (!this.listeners[event]) return;
const index = this.listeners[event]!.indexOf(listener);
if (index > -1) {
this.listeners[event]!.splice(index, 1);
}
}
emit<K extends keyof Events>(
event: K,
...args: Parameters<Events[K]>
): void {
if (!this.listeners[event]) return;
this.listeners[event]!.forEach(listener => listener(...args));
}
}
// 定义事件类型
interface AppEvents {
userLogin: (userId: string, username: string) => void;
userLogout: (userId: string) => void;
dataUpdated: (data: any) => void;
}
const eventBus = new TypedEventEmitter<AppEvents>();
// 订阅事件
const unsubscribe = eventBus.on('userLogin', (userId, username) => {
console.log(`User ${username} (${userId}) logged in`);
});
// 触发事件
eventBus.emit('userLogin', '123', 'John Doe');
// 取消订阅
unsubscribe();
策略模式
支付策略示例
interface PaymentStrategy {
pay(amount: number): Promise<boolean>;
refund(transactionId: string): Promise<boolean>;
}
class AlipayStrategy implements PaymentStrategy {
async pay(amount: number): Promise<boolean> {
console.log(`Paying ${amount} via Alipay`);
// 调用支付宝API
return true;
}
async refund(transactionId: string): Promise<boolean> {
console.log(`Refunding transaction ${transactionId} via Alipay`);
return true;
}
}
class WeChatPayStrategy implements PaymentStrategy {
async pay(amount: number): Promise<boolean> {
console.log(`Paying ${amount} via WeChat Pay`);
// 调用微信支付API
return true;
}
async refund(transactionId: string): Promise<boolean> {
console.log(`Refunding transaction ${transactionId} via WeChat Pay`);
return true;
}
}
class CreditCardStrategy implements PaymentStrategy {
async pay(amount: number): Promise<boolean> {
console.log(`Paying ${amount} via Credit Card`);
// 调用信用卡支付API
return true;
}
async refund(transactionId: string): Promise<boolean> {
console.log(`Refunding transaction ${transactionId} via Credit Card`);
return true;
}
}
class PaymentContext {
private strategy: PaymentStrategy;
setStrategy(strategy: PaymentStrategy): void {
this.strategy = strategy;
}
async executePayment(amount: number): Promise<boolean> {
if (!this.strategy) {
throw new Error('Payment strategy not set');
}
return this.strategy.pay(amount);
}
async executeRefund(transactionId: string): Promise<boolean> {
if (!this.strategy) {
throw new Error('Payment strategy not set');
}
return this.strategy.refund(transactionId);
}
}
// 使用策略模式
const paymentContext = new PaymentContext();
// 根据用户选择设置策略
paymentContext.setStrategy(new AlipayStrategy());
await paymentContext.executePayment(100);
paymentContext.setStrategy(new WeChatPayStrategy());
await paymentContext.executePayment(200);
总结
TypeScript的高级特性使得设计模式的实现更加类型安全和优雅。通过合理运用这些模式,可以:
- 提高代码复用性:通过抽象和接口实现代码的复用
- 增强可维护性:清晰的结构使得代码更易于维护
- 提升可扩展性:新功能的添加不会影响现有代码
- 改善可测试性:依赖注入和接口隔离便于单元测试
在实际项目中,应根据具体需求选择合适的设计模式,避免过度设计。