当前位置: 首页 > news >正文

常用设计模式:工厂方式模式

在软件开发中,对象创建是最基础也是最关键的操作之一。随着项目规模的增长,直接使用 new 关键字创建对象会导致代码高度耦合,难以维护和扩展。工厂方法模式正是为了解决这一问题而生的经典设计模式。

什么是工厂方法模式?

工厂方法模式是一种创建型设计模式,它定义了一个创建对象的接口,但让子类决定实例化哪个类。这种模式将对象的实例化推迟到子类,从而实现了创建逻辑与使用逻辑的分离。

核心概念解析

image

工厂方法模式包含以下几个关键角色:

  • 产品接口(Product Interface):定义了产品对象的通用接口

  • 具体产品(Concrete Products):实现产品接口的具体类

  • 创建者(Creator):声明工厂方法,返回产品对象

  • 具体创建者(Concrete Creators):重写工厂方法,返回具体产品实例

为什么使用工厂方法模式?

解决紧耦合问题

考虑以下紧耦合的代码:

class Car {drive() {console.log('Driving a car');}
}
class Truck {drive() {console.log('Driving a truck');}
}
// 客户端代码直接依赖具体类
const vehicle1 = new Car();
const vehicle1 = new Truck();

这种写法的问题在于,客户端代码直接依赖于具体类,一旦需要添加新的车辆类型或修改创建逻辑,就需要在所有使用的地方进行修改。

实现开闭原则

工厂方法模式帮助你的代码遵循开闭原则:对扩展开放,对修改关闭。你可以添加新的产品类型而无需修改现有代码。

工厂方法模式实现

让我们通过一个完整的示例来理解工厂方法模式。

第一步:定义产品接口

interface Vehicle {drive(): void;getInfo(): string;
}

第二步:实现具体产品类

class Car implements Vehicle {drive() {console.log('Driving a car');}getInfo(): string {return 'This is a car with 4 seats';}
}
class Truck implements Vehicle {drive() {console.log('Driving a truck');}getInfo(): string {return 'This is a truck for heavy loads';}
}
class Motorcycle implements Vehicle {drive() {console.log('Riding a motorcycle');}getInfo(): string {return 'This is a motorcycle with 2 wheels';}
}

第三步:创建抽象创建者类

abstract class VehicleFactory {// 工厂方法public abstract createVehicle(): Vehicle;// 业务逻辑方法public deliverVehicle(): string {const vehicle = this.createVehicle();vehicle.drive();return vehicle.getInfo();}
}

第四步:实现具体创建者类

class CarFactory extends VehicleFactory {public createVehicle(): Vehicle {return new Car();}
}
class TruckFactory extends VehicleFactory {public createVehicle(): Vehicle {return new Truck();}
}
class MotorcycleFactory extends VehicleFactory {public createVehicle(): Vehicle {return new Motorcycle();}
}

第五步:客户端使用

function clientCode(factory: VehicleFactory) {console.log('Client: Delivery process started...');const result = factory.deliverVehicle();console.log(result);
}
// 使用不同的工厂创建不同的产品
console.log('App: Launched with CarFactory.');
clientCode(new CarFactory());
console.log('\nApp: Launched with TruckFactory.');
clientCode(new TruckFactory());
console.log('\nApp: Launched with MotorcycleFactory.');
clientCode(new MotorcycleFactory());

高级应用:参数化工厂方法

在某些场景下,你可能希望通过参数来决定创建哪种产品:

class UniversalVehicleFactory extends VehicleFactory {constructor(private vehicleType: 'car' | 'truck' | 'motorcycle') {super();}public createVehicle(): Vehicle {switch (this.vehicleType) {case 'car':return new Car();case 'truck':return new Truck();case 'motorcycle':return new Motorcycle();default:throw new Error('Unknown vehicle type');}}
}
// 使用参数化工厂
const carFactory = new UniversalVehicleFactory('car');
clientCode(carFactory);

结合 TypeScript 的高级特性

使用泛型增强类型安全

abstract class GenericVehicleFactory {public abstract createVehicle(): T;public deliverVehicle(): string {const vehicle = this.createVehicle();vehicle.drive();return vehicle.getInfo();}
}
class GenericCarFactory extends GenericVehicleFactory {public createVehicle(): Car {return new Car();}
}

利用枚举提高代码可读性

enum VehicleType {CAR = 'car',TRUCK = 'truck',MOTORCYCLE = 'motorcycle'
}
class EnumVehicleFactory extends VehicleFactory {constructor(private type: VehicleType) {super();}public createVehicle(): Vehicle {switch (this.type) {case VehicleType.CAR:return new Car();case VehicleType.TRUCK:return new Truck();case VehicleType.MOTORCYCLE:return new Motorcycle();}}
}

实际应用场景

场景一:UI 组件库

在不同平台(Web、Mobile、Desktop)上创建相同功能的 UI 组件:

interface Button {render(): void;onClick(callback: () => void): void;
}
class WebButton implements Button {render() { console.log('Rendering web button'); }onClick(callback: () => void) { /* web 实现 */ }
}
class MobileButton implements Button {render() { console.log('Rendering mobile button'); }onClick(callback: () => void) { /* mobile 实现 */ }
}
abstract class UIFactory {abstract createButton(): Button;abstract createModal(): Modal; // 假设有 Modal 接口
}
class WebUIFactory extends UIFactory {createButton(): Button { return new WebButton(); }createModal(): Modal { return new WebModal(); }
}

场景二:数据库连接工厂

interface DatabaseConnection {connect(): void;query(sql: string): any[];
}
class MySQLConnection implements DatabaseConnection {connect() { console.log('Connecting to MySQL'); }query(sql: string) { return []; }
}
class PostgreSQLConnection implements DatabaseConnection {connect() { console.log('Connecting to PostgreSQL'); }query(sql: string) { return []; }
}
abstract class DatabaseFactory {abstract createConnection(): DatabaseConnection;
}
class MySQLFactory extends DatabaseFactory {createConnection(): DatabaseConnection {return new MySQLConnection();}
}

真实案例

TypeORM 的 Driver 工厂 使用工厂方法来根据数据库类型创建不同驱动实例。

export class DriverFactory {create(connection: Connection): Driver {switch (connection.options.type) {case "mysql":return new MysqlDriver(connection)case "postgres":return new PostgresDriver(connection)case "sqlite":return new SqliteDriver(connection)// ...}}
}
  • 基于数据库类型返回不同的 Driver 子类

  • 统一入口 create()

  • 使用者不关心具体 driver,只依赖 Driver 接口

工厂方法模式的优势与局限

优势

  1. 避免紧耦合:客户端代码只依赖于抽象接口,不依赖于具体类

  2. 单一职责原则:将创建逻辑集中在一个地方,便于维护

  3. 开闭原则:添加新产品类型时无需修改现有代码

  4. 代码可测试性:可以轻松创建模拟对象进行单元测试

局限

  1. 代码复杂度增加:需要引入多个额外的类和接口

  2. 可能过度设计:对于简单场景,直接实例化可能更合适

实践建议

  1. 适时使用:当预计会有多种类似产品,或创建逻辑比较复杂时使用

  2. 结合依赖注入:在大型应用中,结合依赖注入容器使用效果更佳

  3. 文档化工厂意图:明确每个工厂的职责和适用场景

  4. 考虑简单工厂:如果产品类型不多,可以考虑使用简单工厂模式

总结

工厂方法模式是开发中极其重要的设计模式,它通过将对象的创建与使用分离,显著提高了代码的灵活性和可维护性。虽然会引入一定的复杂度,但在面对变化和扩展需求时,这种前期的投入会带来长期的收益。

掌握工厂方法模式,意味着你不仅学会了如何创建对象,更学会了如何以更加优雅和可持续的方式构建软件系统。在实际项目中,工厂方法模式能够帮助你构建出更加健壮和可扩展的应用程序。

原文链接:https://www.cnblogs.com/guangzan/p/19209210

体验地址:http://www.jnpfsoft.com/?from=001YH

http://www.rkmt.cn/news/85968.html

相关文章:

  • 从图片到文本:多模态数据分析如何重塑企业智能化能力? - 品牌排行榜
  • 智慧工地场景施工设备识别 推土机识别 混凝土搅拌机图像识别 起重机识别工程器械工程车辆 工地工人安全帽泵车识别 yolo图像10287期
  • 解放双手的明日方舟自动化工具:Arknights-Mower 完整使用指南
  • 智能体标准化纪元:Agentic AI基金会(AAIF)成立与全球AI基础设施重构
  • TscanCode静态分析实战指南:从零开始构建代码质量防护体系
  • 从训练到推理:企业级 GenAI 云平台的核心能力与新格局 - 品牌排行榜
  • 基于蒙特卡洛法的规模化电动车有序充放电及负荷预测附PythonMatlab代码
  • 基于蒙特卡诺的风、光模型出力附Matlab代码
  • 3个颠覆性设计:eLabFTW如何重新定义实验室数据管理
  • Wan2.2-T2V-A14B模型可用于游戏过场动画自动生成?
  • 深度解析PC-9801模拟器NP2kai:从硬件仿真到跨平台优化的完整技术指南
  • 2025年知名的轻质alc板厂家最新推荐排行榜 - 行业平台推荐
  • Wan2.2-T2V-A14B与Stable Video Diffusion谁更强?
  • BG3模组管理器完全掌握:从零到精通的终极操作指南
  • 让 AI 真正好用:一个框架提升你的办公效率
  • 用140亿参数打造电影级动态画面:Wan2.2-T2V-A14B实战测评
  • 如何用AI Deadlines轻松管理全球AI会议日程?新手必备的完整指南
  • 3.5倍训练提速终结视觉AI“散装时代“:Ming-UniVision开创统一多模态新纪元
  • Wan2.2-T2V-A14B模型支持按行业模板批量生成视频吗?
  • Wan2.2-T2V-A14B在社交媒体内容批量生成中的价值体现
  • P3405 [USACO16DEC] Cities and States S
  • 2025降重软件实测榜单:AI改写助手与传统工具性能PK
  • ans
  • Wan2.2-T2V-A14B模型能否理解‘一镜到底’拍摄要求?
  • nginx——1day
  • FLUX.1 Kontext:120亿参数重构AI图像编辑,5秒完成专业级修图
  • OpenModScan:免费开源的Modbus主站工具让工业通讯测试变简单
  • WindowResizer终极指南:3分钟掌握高效窗口管理技巧
  • Venera漫画阅读器:全平台无缝阅读体验完全指南
  • 如何快速搭建企业级Bootstrap管理后台?5个实用技巧让你事半功倍