news 2026/9/3 3:34:02

什么是工厂方法模式?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
什么是工厂方法模式?

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

核心概念解析

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<T extends Vehicle> {

public abstract createVehicle(): T;

public deliverVehicle(): string {

const vehicle = this.createVehicle();

vehicle.drive();

return vehicle.getInfo();

}

}

class GenericCarFactory extends GenericVehicleFactory<Car> {

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 接口

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

优势

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

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

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

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

局限

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

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

实践建议

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

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

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 21:56:39

构建企业级Blender-Unity资产流水线:三维数据同步引擎技术架构

构建企业级Blender-Unity资产流水线&#xff1a;三维数据同步引擎技术架构 【免费下载链接】blender-to-unity-fbx-exporter FBX exporter addon for Blender compatible with Unitys coordinate and scaling system. 项目地址: https://gitcode.com/gh_mirrors/bl/blender-t…

作者头像 李华
网站建设 2026/9/2 21:27:29

基于vue的演唱会门票售票预约系统_y425v64z_springboot php python nodejs

目录具体实现截图项目介绍论文大纲核心代码部分展示项目运行指导结论源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作具体实现截图 本系统&#xff08;程序源码数据库调试部署讲解&#xff09;同时还支持java、ThinkPHP、Node.js、Spring B…

作者头像 李华
网站建设 2026/9/2 20:39:58

BookNLP:5大核心功能解析,如何让长文本分析变得简单高效

BookNLP&#xff1a;5大核心功能解析&#xff0c;如何让长文本分析变得简单高效 【免费下载链接】booknlp BookNLP, a natural language processing pipeline for books 项目地址: https://gitcode.com/gh_mirrors/bo/booknlp BookNLP是一个专门为书籍和长文档设计的自然…

作者头像 李华
网站建设 2026/9/2 0:03:29

Neovim代码补全终极指南:从新手到专家的快速上手教程

还在为每次都要手动输入冗长的函数名而浪费时间吗&#xff1f;是否经常因为记不清API参数而频繁切换窗口查看文档&#xff1f;Neovim的现代化代码补全功能将彻底革新你的编程工作流。本指南将带你一步步解锁Neovim的智能提示潜能&#xff0c;让你在编码时享受到前所未有的流畅体…

作者头像 李华
网站建设 2026/9/3 0:27:48

Typst文件嵌入深度指南:告别重复代码的5大核心技巧

你是否曾经在文档编写中陷入这样的困境&#xff1a;同样的内容需要在多个地方重复出现&#xff0c;每次修改都要逐一更新&#xff1f;Typst的文件嵌入功能正是解决这一痛点的利器。作为现代化的排版系统&#xff0c;Typst提供了强大而灵活的文件嵌入机制&#xff0c;让你能够构…

作者头像 李华
网站建设 2026/9/2 21:24:01

SeedVR-3B视频修复实战指南:从模糊到高清的一键蜕变

SeedVR-3B视频修复实战指南&#xff1a;从模糊到高清的一键蜕变 【免费下载链接】SeedVR-3B 项目地址: https://ai.gitcode.com/hf_mirrors/ByteDance-Seed/SeedVR-3B 还在为模糊不清的老视频发愁吗&#xff1f;监控画面太暗看不清车牌&#xff1f;家庭录像充满噪点&am…

作者头像 李华