工厂模式

工厂模式(Factory Pattern)是一种创建型设计模式,用于创建对象而无需指定具体的类。它通过将对象的创建逻辑封装到工厂类中,提供一种灵活的方式来生成不同类型的对象。工厂模式在软件开发中广泛应用,特别是在需要根据条件动态创建对象时。以下是对工厂模式的详细介绍,包括定义、类型、实现方式、优缺点、应用场景和示例代码(以 Java 为例,但概念适用于多种语言)。


1. 定义

  • 工厂模式:通过一个工厂类(或方法)来创建对象,而不是直接使用 new 关键字。工厂模式将对象的创建与使用分离,提高代码的灵活性和可维护性。
  • 核心目标
  • 封装对象创建逻辑。
  • 提供统一的接口来创建不同类型的对象。
  • 支持扩展,符合开闭原则(对扩展开放,对修改关闭)。
  • 关键特点
  • 工厂类负责创建对象。
  • 客户端代码通过工厂接口获取对象,无需了解具体实现。

2. 工厂模式的类型

工厂模式有三种常见变体,每种适用于不同场景:

2.1 简单工厂模式(Simple Factory Pattern)

  • 特点:一个工厂类根据参数创建不同类型的对象(不属于 GoF 的 23 种设计模式,但常作为工厂模式的入门)。
  • 适用场景:对象类型较少,创建逻辑简单。
  • 缺点:违反开闭原则,新增类型需修改工厂类代码。

2.2 工厂方法模式(Factory Method Pattern)

  • 特点:定义一个创建对象的接口,让子类决定实例化哪个类。每个具体产品对应一个具体工厂。
  • 适用场景:需要支持多种产品,且产品可能扩展。
  • 优点:符合开闭原则,易于扩展。

2.3 抽象工厂模式(Abstract Factory Pattern)

  • 特点:提供一个接口,用于创建一系列相关或依赖对象的家族,而无需指定具体类。
  • 适用场景:需要创建一组相关对象(如 UI 组件的不同风格)。
  • 优点:支持产品族的创建,保持一致性。

3. 实现方式

以下分别展示三种工厂模式的实现(以 Java 为例)。

3.1 简单工厂模式

创建一个工厂类,根据参数返回不同类型的对象。

// 产品接口
interface Product {
    void use();
}

// 具体产品
class ConcreteProductA implements Product {
    public void use() {
        System.out.println("Using Product A");
    }
}

class ConcreteProductB implements Product {
    public void use() {
        System.out.println("Using Product B");
    }
}

// 简单工厂
class SimpleFactory {
    public static Product createProduct(String type) {
        if ("A".equals(type)) {
            return new ConcreteProductA();
        } else if ("B".equals(type)) {
            return new ConcreteProductB();
        }
        return null;
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Product productA = SimpleFactory.createProduct("A");
        productA.use(); // 输出: Using Product A

        Product productB = SimpleFactory.createProduct("B");
        productB.use(); // 输出: Using Product B
    }
}
  • 说明
  • SimpleFactory 根据参数 type 创建不同产品。
  • 缺点:新增产品类型需修改 createProduct 方法。

3.2 工厂方法模式

为每个产品定义一个具体工厂,工厂类与产品类一一对应。

// 产品接口
interface Product {
    void use();
}

// 具体产品
class ConcreteProductA implements Product {
    public void use() {
        System.out.println("Using Product A");
    }
}

class ConcreteProductB implements Product {
    public void use() {
        System.out.println("Using Product B");
    }
}

// 工厂接口
interface Factory {
    Product createProduct();
}

// 具体工厂
class ConcreteFactoryA implements Factory {
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

class ConcreteFactoryB implements Factory {
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Factory factoryA = new ConcreteFactoryA();
        Product productA = factoryA.createProduct();
        productA.use(); // 输出: Using Product A

        Factory factoryB = new ConcreteFactoryB();
        Product productB = factoryB.createProduct();
        productB.use(); // 输出: Using Product B
    }
}
  • 说明
  • 每个产品有对应的工厂类,新增产品只需添加新工厂和新产品类。
  • 符合开闭原则,扩展性更好。

3.3 抽象工厂模式

创建一组相关的产品(如按钮和文本框的 UI 组件)。

// 抽象产品接口
interface Button {
    void render();
}

interface TextField {
    void display();
}

// 具体产品 - Windows 风格
class WindowsButton implements Button {
    public void render() {
        System.out.println("Rendering Windows Button");
    }
}

class WindowsTextField implements TextField {
    public void display() {
        System.out.println("Displaying Windows TextField");
    }
}

// 具体产品 - Mac 风格
class MacButton implements Button {
    public void render() {
        System.out.println("Rendering Mac Button");
    }
}

class MacTextField implements TextField {
    public void display() {
        System.out.println("Displaying Mac TextField");
    }
}

// 抽象工厂接口
interface UIFactory {
    Button createButton();
    TextField createTextField();
}

// 具体工厂
class WindowsFactory implements UIFactory {
    public Button createButton() {
        return new WindowsButton();
    }
    public TextField createTextField() {
        return new WindowsTextField();
    }
}

class MacFactory implements UIFactory {
    public Button createButton() {
        return new MacButton();
    }
    public TextField createTextField() {
        return new MacTextField();
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        UIFactory windowsFactory = new WindowsFactory();
        Button winButton = windowsFactory.createButton();
        TextField winTextField = windowsFactory.createTextField();
        winButton.render(); // 输出: Rendering Windows Button
        winTextField.display(); // 输出: Displaying Windows TextField

        UIFactory macFactory = new MacFactory();
        Button macButton = macFactory.createButton();
        TextField macTextField = macFactory.createTextField();
        macButton.render(); // 输出: Rendering Mac Button
        macTextField.display(); // 输出: Displaying Mac TextField
    }
}
  • 说明
  • 抽象工厂模式支持创建一组相关产品(如 Windows 或 Mac 的 UI 组件)。
  • 客户端通过工厂接口创建一致的产品族。

4. 优缺点

优点

  • 封装创建逻辑:客户端无需关心具体类的实例化过程。
  • 提高灵活性:通过工厂接口可以动态选择创建的对象类型。
  • 符合开闭原则(工厂方法和抽象工厂):新增产品无需修改现有代码。
  • 一致性(抽象工厂):确保创建的产品族兼容。

缺点

  • 代码复杂性:工厂方法和抽象工厂会引入额外的类,增加代码量。
  • 简单工厂的局限:新增产品需修改工厂类,违反开闭原则。
  • 维护成本:在大型系统中,管理多个工厂类可能较复杂。

5. 应用场景

  • 动态创建对象:根据配置或条件创建不同类型的对象(如数据库驱动:MySQL、PostgreSQL)。
  • UI 框架:创建不同风格的 UI 组件(如 Windows、Mac 风格)。
  • 插件系统:动态加载不同插件或模块。
  • 日志框架:创建不同类型的日志记录器(如文件日志、控制台日志)。
  • 对象池管理:管理可重用的对象实例。

6. 与其他模式的对比

  • 单例模式 vs 工厂模式
  • 单例模式:确保一个类只有一个实例。
  • 工厂模式:关注创建不同类型的对象,实例数量不限。
  • 工厂方法 vs 抽象工厂
  • 工厂方法:为单一产品类型提供创建接口。
  • 抽象工厂:为产品族提供创建接口。
  • 工厂模式 vs 建造者模式
  • 工厂模式:关注创建完整对象。
  • 建造者模式:关注分步构建复杂对象。

7. 在其他语言中的实现

Objective-C 工厂方法

// Product.h
@protocol Product <NSObject>
- (void)use;
@end

// ConcreteProductA.h
@interface ConcreteProductA : NSObject <Product>
@end

// ConcreteProductA.m
@implementation ConcreteProductA
- (void)use {
    NSLog(@"Using Product A");
}
@end

// ConcreteProductB.h
@interface ConcreteProductB : NSObject <Product>
@end

// ConcreteProductB.m
@implementation ConcreteProductB
- (void)use {
    NSLog(@"Using Product B");
}
@end

// Factory.h
@protocol Factory <NSObject>
- (id<Product>)createProduct;
@end

// ConcreteFactoryA.h
@interface ConcreteFactoryA : NSObject <Factory>
@end

// ConcreteFactoryA.m
@implementation ConcreteFactoryA
- (id<Product>)createProduct {
    return [[ConcreteProductA alloc] init];
}
@end

// 使用示例
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        id<Factory> factory = [[ConcreteFactoryA alloc] init];
        id<Product> product = [factory createProduct];
        [product use]; // 输出: Using Product A
    }
    return 0;
}

JavaScript 简单工厂

class ProductA {
    use() {
        console.log("Using Product A");
    }
}

class ProductB {
    use() {
        console.log("Using Product B");
    }
}

class SimpleFactory {
    static createProduct(type) {
        if (type === "A") {
            return new ProductA();
        } else if (type === "B") {
            return new ProductB();
        }
        return null;
    }
}

// 使用
const productA = SimpleFactory.createProduct("A");
productA.use(); // 输出: Using Product A

8. 注意事项

  • 选择合适的工厂模式
  • 简单工厂适合小型项目,逻辑简单。
  • 工厂方法适合需要扩展的场景。
  • 抽象工厂适合创建相关产品族。
  • 性能考虑:工厂模式可能增加对象创建的间接层,注意性能开销。
  • 框架支持:在现代框架(如 Spring)中,工厂模式常由 IoC 容器实现(如 BeanFactory)。
  • 测试性:工厂模式便于 Mock 测试,可以通过注入不同工厂模拟行为。

9. 总结

  • 工厂模式通过封装对象创建逻辑,提高代码灵活性和可维护性。
  • 三种变体
  • 简单工厂:简单但扩展性差。
  • 工厂方法:符合开闭原则,适合单一产品扩展。
  • 抽象工厂:适合创建相关产品族。
  • 应用场景:动态对象创建、UI 组件、插件系统等。
  • 推荐实践:优先选择工厂方法或抽象工厂,结合依赖注入框架使用。

如果你需要更详细的代码示例(特定语言或场景,如 iOS UIKit 工厂)、与其他模式的对比,或深入探讨某变体的实现,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注