TypeScript设计模式:何时以及为何使用
\n\n想象一下,你在建造一栋房子。你可以随意堆砌砖块,房子很可能不会倒塌。但住在里面会舒适吗?恐怕不会。软件架构同样如此——只不过砖块换成了类和函数。TypeScript设计模式是解决典型架构问题的经过验证的蓝图。但和任何工具一样,需要明智地使用它们。
\n\n在本文中,我们不会复述GoF(四人帮)书籍中的枯燥理论。相反,我们将探讨哪些TypeScript设计模式在现代开发中真正必要,它们何时能拯救项目,何时只会增加麻烦。开始吧!
\n\n为什么TypeScript改变了游戏规则?
\n\n在深入模式之前,让我们回顾一下TypeScript的主要特点——静态类型。在JavaScript中,我们经常使用模式来弥补语言的动态特性。例如,工厂方法(Factory Method)有助于隐藏对象创建的复杂性。在TypeScript中,这种复杂性通常可以通过接口和泛型轻松解决。
\n\n但这并不意味着模式已经过时。相反,TypeScript使它们更具表现力和安全性。编译器会检查你是否正确实现了结构,并防止你犯低级错误。这就是TypeScript发挥GoF模式力量的地方。
\n\n最常用的5种设计模式
\n\n1. Singleton(单例)——一个正好,两个多余
\n\n何时使用:整个应用程序只需要一个类实例。经典示例包括日志记录器、应用程序配置、数据库连接。
\n\n为什么在TypeScript中:TypeScript允许创建线程安全且类型安全的Singleton。没有它,你可能会创建数十个对象,浪费内存并混淆状态。
\n\n代码示例:
\n\nclass DatabaseConnection {\n private static instance: DatabaseConnection;\n private connectionString: string;\n\n private constructor(connectionString: string) {\n this.connectionString = connectionString;\n // 模拟连接\n console.log(`连接到 ${connectionString}`);\n }\n\n static getInstance(connectionString: string): DatabaseConnection {\n if (!DatabaseConnection.instance) {\n DatabaseConnection.instance = new DatabaseConnection(connectionString);\n }\n return DatabaseConnection.instance;\n }\n\n query(sql: string): void {\n console.log(`执行查询: ${sql}`);\n }\n}\n\n// 使用\nconst db = DatabaseConnection.getInstance('postgres://localhost:5432/mydb');\ndb.query('SELECT * FROM users');\n\n// 尝试创建另一个连接将返回同一实例\nconst db2 = DatabaseConnection.getInstance('postgres://localhost:5432/mydb');\nconsole.log(db === db2); // true\n\n反模式:不要为了单例而创建单例。如果对象可以存在多个具有不同状态的实例(例如,连接到不同数据库的不同连接),那么单例就是有害的。
\n\n2. Factory Method(工厂方法)——轻松创建对象
\n\n何时使用:你事先不知道需要创建哪个具体对象。或者创建过程复杂且需要逻辑。
\n\n为什么在TypeScript中:工厂方法与接口和泛型配合得很好。你可以在不丢失类型的情况下获得灵活性。
\n\n代码示例:
\n\n// 抽象产品\ninterface Notification {\n send(message: string): void;\n}\n\n// 具体产品\nclass EmailNotification implements Notification {\n send(message: string): void {\n console.log(`发送邮件: ${message}`);\n }