工厂型设计模式对比


目录

  1. 工厂型设计模式简介

  2. 简单工厂模式(Simple Factory Pattern)

  3. 工厂方法模式(Factory Method Pattern)

  4. 抽象工厂模式(Abstract Factory Pattern)

  5. 三种工厂模式的对比

  6. 选择合适的工厂模式

  7. 总结

  8. 参考资料


1. 工厂型设计模式简介

工厂型设计模式是一类用于创建对象的设计模式,旨在通过将对象的创建逻辑封装在工厂类中,使得客户端无需直接实例化具体类,从而实现对象创建的解耦。工厂型模式主要包括:

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

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

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

每种模式在对象创建的灵活性、扩展性和复杂度上有所不同,适用于不同的应用场景。


2. 简单工厂模式(Simple Factory Pattern)

2.1. 定义

简单工厂模式是一种创建型设计模式,通过一个工厂类根据传入的参数决定创建哪一种具体产品类的实例。它将对象的创建过程集中在一个工厂类中,客户端通过工厂类提供的接口获取对象,无需直接实例化具体类。

2.2. 结构

  • 工厂类(Factory):负责创建具体产品的类,包含一个静态方法用于根据参数创建并返回不同类型的产品。

  • 产品接口(Product):定义产品的公共接口或抽象类。

  • 具体产品类(ConcreteProduct):实现产品接口的具体类。

2.3. UML 类图

+----------------------------------------+
|     Factory                            |
+----------------------------------------+
| + createProduct(type: String): Product |
+----------------------------------------+
          |
          |
+------------------+        +------------------+
|     Product      |<-------| ConcreteProductA |
+------------------+        +------------------+
| + use()          |        | + use()          |
+------------------+        +------------------+
                            +------------------+
                            | ConcreteProductB |
                            +------------------+
                            | + use()          |
                            +------------------+

2.4. 实现

Java 实现

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

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

// 具体产品类B
public class ConcreteProductB implements Product {
    public void use() {
        System.out.println("使用具体产品B");
    }
}

// 工厂类
public class SimpleFactory {
    public static Product createProduct(String type) {
        if (type == null) {
            throw new IllegalArgumentException("产品类型不能为空");
        }
        switch (type.toUpperCase()) {
            case "A":
                return new ConcreteProductA();
            case "B":
                return new ConcreteProductB();
            default:
                throw new IllegalArgumentException("未知的产品类型: " + type);
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Product productA = SimpleFactory.createProduct("A");
        productA.use(); // 输出: 使用具体产品A

        Product productB = SimpleFactory.createProduct("B");
        productB.use(); // 输出: 使用具体产品B
    }
}

Python 实现

from abc import ABC, abstractmethod

# 产品接口
class Product(ABC):
    @abstractmethod
    def use(self):
        pass

# 具体产品类A
class ConcreteProductA(Product):
    def use(self):
        print("使用具体产品A")

# 具体产品类B
class ConcreteProductB(Product):
    def use(self):
        print("使用具体产品B")

# 工厂类
class SimpleFactory:
    @staticmethod
    def create_product(product_type: str) -> Product:
        if product_type.upper() == "A":
            return ConcreteProductA()
        elif product_type.upper() == "B":
            return ConcreteProductB()
        else:
            raise ValueError(f"未知的产品类型: {product_type}")

# 客户端代码
if __name__ == "__main__":
    factory = SimpleFactory()
    product_a = factory.create_product("A")
    product_a.use()  # 输出: 使用具体产品A

    product_b = factory.create_product("B")
    product_b.use()  # 输出: 使用具体产品B

2.5. 优缺点

优点:

  1. 封装对象创建:将对象的创建过程集中在工厂类中,客户端无需了解具体类的创建细节。

  2. 简化客户端代码:客户端通过工厂方法获取对象,减少了直接实例化的代码量。

  3. 集中管理对象创建:所有对象的创建由工厂类统一管理,便于维护和扩展。

  4. 符合开闭原则:通过修改工厂类,可以增加新产品的支持,而无需修改客户端代码。

缺点:

  1. 违反单一职责原则:工厂类承担了创建所有产品的职责,可能导致工厂类过于庞大。

  2. 增加系统复杂性:每增加一种产品类型,都需要修改工厂类,增加了工厂类的复杂性。

  3. 不易扩展:对于产品种类频繁变化的系统,简单工厂模式可能不够灵活,难以适应需求变化。


3. 工厂方法模式(Factory Method Pattern)

3.1. 定义

工厂方法模式是一种创建型设计模式,通过定义一个创建对象的接口,让子类决定实例化哪一个类。它使得类的实例化延迟到子类。工厂方法模式适用于产品类比较多或复杂,需要通过子类来进行扩展的场景。

3.2. 结构

  • 产品接口(Product):定义产品的公共接口。

  • 具体产品类(ConcreteProduct):实现产品接口的具体类。

  • 工厂接口(Creator):声明工厂方法,用于创建产品。

  • 具体工厂类(ConcreteCreator):实现工厂接口,创建具体产品。

3.3. UML 类图

+------------------+       +------------------+
|      Creator     |<>-----|    Product       |
+------------------+       +------------------+
| + factoryMethod()|       | + operation()    |
+------------------+       +------------------+
        /_\
         |
+----------------------+    +----------------------+
| ConcreteCreatorA     |    | ConcreteCreatorB     |
+----------------------+    +----------------------+
| + factoryMethod()    |    | + factoryMethod()    |
+----------------------+    +----------------------+
         |                           |
+------------------+        +------------------+
| ConcreteProductA |        | ConcreteProductB |
+------------------+        +------------------+
| + operation()    |        | + operation()    |
+------------------+        +------------------+

3.4. 实现

Java 实现

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

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

// 具体产品类B
public class ConcreteProductB implements Product {
    public void use() {
        System.out.println("使用具体产品B");
    }
}

// 工厂接口
public abstract class Creator {
    public abstract Product factoryMethod();
    
    public void someOperation() {
        Product product = factoryMethod();
        product.use();
    }
}

// 具体工厂类A
public class ConcreteCreatorA extends Creator {
    public Product factoryMethod() {
        return new ConcreteProductA();
    }
}

// 具体工厂类B
public class ConcreteCreatorB extends Creator {
    public Product factoryMethod() {
        return new ConcreteProductB();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Creator creatorA = new ConcreteCreatorA();
        creatorA.someOperation(); // 输出: 使用具体产品A

        Creator creatorB = new ConcreteCreatorB();
        creatorB.someOperation(); // 输出: 使用具体产品B
    }
}

Python 实现

from abc import ABC, abstractmethod

# 产品接口
class Product(ABC):
    @abstractmethod
    def use(self):
        pass

# 具体产品类A
class ConcreteProductA(Product):
    def use(self):
        print("使用具体产品A")

# 具体产品类B
class ConcreteProductB(Product):
    def use(self):
        print("使用具体产品B")

# 工厂接口
class Creator(ABC):
    @abstractmethod
    def factory_method(self) -> Product:
        pass
    
    def some_operation(self):
        product = self.factory_method()
        product.use()

# 具体工厂类A
class ConcreteCreatorA(Creator):
    def factory_method(self) -> Product:
        return ConcreteProductA()

# 具体工厂类B
class ConcreteCreatorB(Creator):
    def factory_method(self) -> Product:
        return ConcreteProductB()

# 客户端代码
if __name__ == "__main__":
    creator_a = ConcreteCreatorA()
    creator_a.some_operation()  # 输出: 使用具体产品A

    creator_b = ConcreteCreatorB()
    creator_b.some_operation()  # 输出: 使用具体产品B

3.5. 优缺点

优点:

  1. 符合开闭原则:通过引入新的具体工厂和产品类,可以扩展系统功能,而无需修改已有代码。

  2. 封装对象创建:将对象的创建过程封装在具体工厂类中,客户端无需了解具体类的创建细节。

  3. 提高代码复用性和可维护性:不同的具体工厂类可以复用相同的创建逻辑,便于维护和管理。

缺点:

  1. 增加类的数量:每种产品类型都需要对应一个具体工厂类,可能导致类的数量增加。

  2. 结构复杂性:相对于简单工厂模式,工厂方法模式的结构更加复杂,需要定义抽象工厂接口和具体工厂类。

  3. 不适用于产品种类不多的场景:当产品种类较少且不易扩展时,工厂方法模式可能显得过于繁琐。


4. 抽象工厂模式(Abstract Factory Pattern)

4.1. 定义

抽象工厂模式是一种创建型设计模式,提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。抽象工厂模式适用于产品族(Family)不变的情况下创建不同系列的产品。

4.2. 结构

  • 抽象工厂接口(AbstractFactory):声明创建一系列相关对象的方法。

  • 具体工厂类(ConcreteFactory):实现抽象工厂接口,创建具体的相关对象。

  • 抽象产品接口(AbstractProduct):定义一类产品的公共接口。

  • 具体产品类(ConcreteProduct):实现抽象产品接口的具体类。

4.3. UML 类图

+---------------------+       +---------------------+
|   AbstractFactory   |<>-----|    AbstractProduct  |
+---------------------+       +---------------------+
| + createProductA()  |       | + operationA()      |
| + createProductB()  |       | + operationB()      |
+---------------------+       +---------------------+
        /_\                             /_\
         |                               |
+---------------------+       +---------------------+
|  ConcreteFactory1   |       |  ConcreteProduct1A  |
+---------------------+       +---------------------+
| + createProductA()  |       | + operationA()      |
| + createProductB()  |       | + operationB()      |
+---------------------+       +---------------------+

+---------------------+       +---------------------+
|  ConcreteFactory2   |       |  ConcreteProduct2A  |
+---------------------+       +---------------------+
| + createProductA()  |       | + operationA()      |
| + createProductB()  |       | + operationB()      |
+---------------------+       +---------------------+

4.4. 实现

Java 实现

// 抽象产品接口A
public interface AbstractProductA {
    void doSomethingA();
}

// 具体产品类A1
public class ConcreteProductA1 implements AbstractProductA {
    public void doSomethingA() {
        System.out.println("ConcreteProductA1 的操作A");
    }
}

// 具体产品类A2
public class ConcreteProductA2 implements AbstractProductA {
    public void doSomethingA() {
        System.out.println("ConcreteProductA2 的操作A");
    }
}

// 抽象产品接口B
public interface AbstractProductB {
    void doSomethingB();
}

// 具体产品类B1
public class ConcreteProductB1 implements AbstractProductB {
    public void doSomethingB() {
        System.out.println("ConcreteProductB1 的操作B");
    }
}

// 具体产品类B2
public class ConcreteProductB2 implements AbstractProductB {
    public void doSomethingB() {
        System.out.println("ConcreteProductB2 的操作B");
    }
}

// 抽象工厂接口
public interface AbstractFactory {
    AbstractProductA createProductA();
    AbstractProductB createProductB();
}

// 具体工厂类1
public class ConcreteFactory1 implements AbstractFactory {
    public AbstractProductA createProductA() {
        return new ConcreteProductA1();
    }
    
    public AbstractProductB createProductB() {
        return new ConcreteProductB1();
    }
}

// 具体工厂类2
public class ConcreteFactory2 implements AbstractFactory {
    public AbstractProductA createProductA() {
        return new ConcreteProductA2();
    }
    
    public AbstractProductB createProductB() {
        return new ConcreteProductB2();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        AbstractProductA productA1 = factory1.createProductA();
        AbstractProductB productB1 = factory1.createProductB();
        productA1.doSomethingA(); // 输出: ConcreteProductA1 的操作A
        productB1.doSomethingB(); // 输出: ConcreteProductB1 的操作B

        AbstractFactory factory2 = new ConcreteFactory2();
        AbstractProductA productA2 = factory2.createProductA();
        AbstractProductB productB2 = factory2.createProductB();
        productA2.doSomethingA(); // 输出: ConcreteProductA2 的操作A
        productB2.doSomethingB(); // 输出: ConcreteProductB2 的操作B
    }
}

Python 实现

from abc import ABC, abstractmethod

# 抽象产品接口A
class AbstractProductA(ABC):
    @abstractmethod
    def do_something_a(self):
        pass

# 具体产品类A1
class ConcreteProductA1(AbstractProductA):
    def do_something_a(self):
        print("ConcreteProductA1 的操作A")

# 具体产品类A2
class ConcreteProductA2(AbstractProductA):
    def do_something_a(self):
        print("ConcreteProductA2 的操作A")

# 抽象产品接口B
class AbstractProductB(ABC):
    @abstractmethod
    def do_something_b(self):
        pass

# 具体产品类B1
class ConcreteProductB1(AbstractProductB):
    def do_something_b(self):
        print("ConcreteProductB1 的操作B")

# 具体产品类B2
class ConcreteProductB2(AbstractProductB):
    def do_something_b(self):
        print("ConcreteProductB2 的操作B")

# 抽象工厂接口
class AbstractFactory(ABC):
    @abstractmethod
    def create_product_a(self) -> AbstractProductA:
        pass

    @abstractmethod
    def create_product_b(self) -> AbstractProductB:
        pass

# 具体工厂类1
class ConcreteFactory1(AbstractFactory):
    def create_product_a(self) -> AbstractProductA:
        return ConcreteProductA1()

    def create_product_b(self) -> AbstractProductB:
        return ConcreteProductB1()

# 具体工厂类2
class ConcreteFactory2(AbstractFactory):
    def create_product_a(self) -> AbstractProductA:
        return ConcreteProductA2()

    def create_product_b(self) -> AbstractProductB:
        return ConcreteProductB2()

# 客户端代码
if __name__ == "__main__":
    factory1 = ConcreteFactory1()
    productA1 = factory1.create_product_a()
    productB1 = factory1.create_product_b()
    productA1.do_something_a()  # 输出: ConcreteProductA1 的操作A
    productB1.do_something_b()  # 输出: ConcreteProductB1 的操作B

    factory2 = ConcreteFactory2()
    productA2 = factory2.create_product_a()
    productB2 = factory2.create_product_b()
    productA2.do_something_a()  # 输出: ConcreteProductA2 的操作A
    productB2.do_something_b()  # 输出: ConcreteProductB2 的操作B

4.5. 优缺点

优点:

  1. 创建一系列相关对象:通过一个工厂接口,可以创建一系列相关或相互依赖的对象,确保产品族的兼容性。

  2. 符合开闭原则:通过新增具体工厂和产品类,可以扩展系统功能,而无需修改已有代码。

  3. 封装具体类:客户端无需了解具体产品类的实现,降低了系统的耦合度。

  4. 增强系统的灵活性和可扩展性:不同的工厂可以创建不同的产品族,适应多变的需求。

缺点:

  1. 增加类的数量:每增加一个产品族,都需要新增一个具体工厂类和相应的具体产品类,可能导致类的数量迅速增加。

  2. 复杂性提高:结构相对复杂,需要定义抽象工厂接口和多个具体工厂类,增加了系统的复杂性。

  3. 不适用于单一产品的创建:如果系统只需要创建单一类型的产品,抽象工厂模式可能显得过于复杂。


5. 三种工厂模式的对比

5.1. 结构对比

下表展示了简单工厂模式工厂方法模式抽象工厂模式的主要结构和关系。

特性 简单工厂模式 工厂方法模式 抽象工厂模式
主要角色 工厂类、产品接口、具体产品类 抽象工厂类(Creator)、具体工厂类、产品接口、具体产品类 抽象工厂接口、具体工厂类、多个产品接口、具体产品类
工厂类的数量 一个简单工厂类 抽象工厂类+多个具体工厂类 抽象工厂接口+多个具体工厂类
产品族的支持 不支持,主要创建单一类型的产品 不支持,主要创建单一类型的产品 支持,创建一系列相关的产品
扩展性 不易扩展,新增产品需修改工厂类 易扩展,新增产品只需新增具体工厂和产品类 易扩展,新增产品族需新增具体工厂和产品类
依赖关系 客户端依赖于工厂类和产品接口 客户端依赖于抽象工厂接口和产品接口 客户端依赖于抽象工厂接口和多个产品接口

5.2. 灵活性与扩展性

  • 简单工厂模式

    • 灵活性:相对较低,工厂类需要知道所有具体产品类,增加新产品需要修改工厂类。

    • 扩展性:不易扩展,违背开闭原则。

  • 工厂方法模式

    • 灵活性:较高,通过子类工厂决定具体产品类,客户端不需知道具体产品类。

    • 扩展性:易于扩展,符合开闭原则。

  • 抽象工厂模式

    • 灵活性:非常高,支持创建一系列相关产品,确保产品间的兼容性。

    • 扩展性:易于扩展,新增产品族只需新增具体工厂和产品类。

5.3. 适用场景

  • 简单工厂模式

    • 适用场景

      • 对象创建过程相对简单,不需要创建多个相关对象。

      • 系统中产品类较少且不易频繁变动。

      • 需要通过参数决定创建哪一种具体产品类。

  • 工厂方法模式

    • 适用场景

      • 系统中产品类较多或经常变化。

      • 需要通过子类工厂创建不同的产品类。

      • 系统遵循开闭原则,需要易于扩展。

  • 抽象工厂模式

    • 适用场景

      • 系统需要创建一系列相关或相互依赖的对象。

      • 需要确保产品族的兼容性。

      • 系统需要独立于具体产品类的创建。

5.4. 优缺点对比

特性 简单工厂模式 工厂方法模式 抽象工厂模式
优点 - 封装对象创建过程
- 简化客户端代码
- 集中管理对象创建
- 符合开闭原则
- 封装对象创建
- 提高代码复用性和可维护性
- 创建一系列相关对象
- 符合开闭原则
- 封装具体类
- 增强系统灵活性和可扩展性
缺点 - 违反单一职责原则
- 增加系统复杂性
- 不易扩展
- 增加类的数量
- 结构复杂性
- 不适用于单一产品创建
- 增加类的数量
- 结构复杂性
- 不适用于单一产品创建
适用场景 - 对象创建过程简单
- 产品类较少
- 需要通过参数创建对象
- 产品类较多或经常变化
- 需要通过子类工厂创建对象
- 需要创建一系列相关对象
- 需要确保产品族的兼容性

6. 选择合适的工厂模式

选择合适的工厂模式需要根据具体的需求和系统的复杂性来决定。以下是一些选择指南:

6.1. 使用简单工厂模式的情况

  • 对象创建过程相对简单:对象的创建逻辑不复杂,不需要创建一系列相关的对象。

  • 产品类较少且不易频繁变化:系统中产品类数量有限,且新增产品类的频率不高。

  • 客户端仅需通过参数决定创建哪一种产品:不需要通过子类化来决定具体的产品类。

6.2. 使用工厂方法模式的情况

  • 系统中产品类较多或经常变化:需要通过子类化来管理不同的产品类,便于扩展。

  • 遵循开闭原则:希望通过新增子类来支持新的产品,而不修改已有代码。

  • 需要通过子类工厂创建不同的产品:不同的工厂子类负责创建不同的产品类,实现职责分离。

6.3. 使用抽象工厂模式的情况

  • 需要创建一系列相关或相互依赖的对象:确保产品族之间的兼容性,如UI组件(按钮、文本框、窗口等)。

  • 系统需要独立于具体产品类的创建:客户端只依赖于抽象工厂和抽象产品接口,减少对具体类的依赖。

  • 需要确保产品族的协同工作:通过同一个具体工厂创建的产品对象能够协同工作,符合设计的一致性。


7. 总结

工厂型设计模式通过不同的方式封装对象的创建过程,降低系统的耦合度,提升代码的可维护性和扩展性。以下是对简单工厂模式工厂方法模式抽象工厂模式的总结:

  • 简单工厂模式

    • 特点:集中管理对象创建,通过参数决定具体产品类。

    • 适用场景:对象创建过程简单,产品类较少且不易频繁变化。

    • 优缺点:封装对象创建、简化客户端代码,但违反单一职责原则、不易扩展。

  • 工厂方法模式

    • 特点:通过子类工厂决定具体产品类,实现工厂接口。

    • 适用场景:产品类较多或经常变化,需符合开闭原则。

    • 优缺点:符合开闭原则、封装对象创建,但增加类的数量、结构复杂。

  • 抽象工厂模式

    • 特点:创建一系列相关对象,确保产品族的兼容性。

    • 适用场景:需要创建相关或相互依赖的对象,确保产品族的一致性。

    • 优缺点:创建一系列相关对象、符合开闭原则,但增加类的数量、结构复杂。

选择合适的工厂模式应根据系统的具体需求、产品类的数量和变化频率以及系统的扩展性要求来决定。合理运用工厂型设计模式,可以显著提升系统的设计质量和代码的可维护性。


8. 参考资料