目录¶
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. 优缺点¶
优点:
封装对象创建:将对象的创建过程集中在工厂类中,客户端无需了解具体类的创建细节。
简化客户端代码:客户端通过工厂方法获取对象,减少了直接实例化的代码量。
集中管理对象创建:所有对象的创建由工厂类统一管理,便于维护和扩展。
符合开闭原则:通过修改工厂类,可以增加新产品的支持,而无需修改客户端代码。
缺点:
违反单一职责原则:工厂类承担了创建所有产品的职责,可能导致工厂类过于庞大。
增加系统复杂性:每增加一种产品类型,都需要修改工厂类,增加了工厂类的复杂性。
不易扩展:对于产品种类频繁变化的系统,简单工厂模式可能不够灵活,难以适应需求变化。
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. 优缺点¶
优点:
符合开闭原则:通过引入新的具体工厂和产品类,可以扩展系统功能,而无需修改已有代码。
封装对象创建:将对象的创建过程封装在具体工厂类中,客户端无需了解具体类的创建细节。
提高代码复用性和可维护性:不同的具体工厂类可以复用相同的创建逻辑,便于维护和管理。
缺点:
增加类的数量:每种产品类型都需要对应一个具体工厂类,可能导致类的数量增加。
结构复杂性:相对于简单工厂模式,工厂方法模式的结构更加复杂,需要定义抽象工厂接口和具体工厂类。
不适用于产品种类不多的场景:当产品种类较少且不易扩展时,工厂方法模式可能显得过于繁琐。
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. 优缺点¶
优点:
创建一系列相关对象:通过一个工厂接口,可以创建一系列相关或相互依赖的对象,确保产品族的兼容性。
符合开闭原则:通过新增具体工厂和产品类,可以扩展系统功能,而无需修改已有代码。
封装具体类:客户端无需了解具体产品类的实现,降低了系统的耦合度。
增强系统的灵活性和可扩展性:不同的工厂可以创建不同的产品族,适应多变的需求。
缺点:
增加类的数量:每增加一个产品族,都需要新增一个具体工厂类和相应的具体产品类,可能导致类的数量迅速增加。
复杂性提高:结构相对复杂,需要定义抽象工厂接口和多个具体工厂类,增加了系统的复杂性。
不适用于单一产品的创建:如果系统只需要创建单一类型的产品,抽象工厂模式可能显得过于复杂。
5. 三种工厂模式的对比¶
5.1. 结构对比¶
下表展示了简单工厂模式、工厂方法模式和抽象工厂模式的主要结构和关系。
特性 | 简单工厂模式 | 工厂方法模式 | 抽象工厂模式 |
---|---|---|---|
主要角色 | 工厂类、产品接口、具体产品类 | 抽象工厂类(Creator)、具体工厂类、产品接口、具体产品类 | 抽象工厂接口、具体工厂类、多个产品接口、具体产品类 |
工厂类的数量 | 一个简单工厂类 | 抽象工厂类+多个具体工厂类 | 抽象工厂接口+多个具体工厂类 |
产品族的支持 | 不支持,主要创建单一类型的产品 | 不支持,主要创建单一类型的产品 | 支持,创建一系列相关的产品 |
扩展性 | 不易扩展,新增产品需修改工厂类 | 易扩展,新增产品只需新增具体工厂和产品类 | 易扩展,新增产品族需新增具体工厂和产品类 |
依赖关系 | 客户端依赖于工厂类和产品接口 | 客户端依赖于抽象工厂接口和产品接口 | 客户端依赖于抽象工厂接口和多个产品接口 |
5.2. 灵活性与扩展性¶
简单工厂模式:
灵活性:相对较低,工厂类需要知道所有具体产品类,增加新产品需要修改工厂类。
扩展性:不易扩展,违背开闭原则。
工厂方法模式:
灵活性:较高,通过子类工厂决定具体产品类,客户端不需知道具体产品类。
扩展性:易于扩展,符合开闭原则。
抽象工厂模式:
灵活性:非常高,支持创建一系列相关产品,确保产品间的兼容性。
扩展性:易于扩展,新增产品族只需新增具体工厂和产品类。
5.3. 适用场景¶
简单工厂模式:
适用场景:
对象创建过程相对简单,不需要创建多个相关对象。
系统中产品类较少且不易频繁变动。
需要通过参数决定创建哪一种具体产品类。
工厂方法模式:
适用场景:
系统中产品类较多或经常变化。
需要通过子类工厂创建不同的产品类。
系统遵循开闭原则,需要易于扩展。
抽象工厂模式:
适用场景:
系统需要创建一系列相关或相互依赖的对象。
需要确保产品族的兼容性。
系统需要独立于具体产品类的创建。
5.4. 优缺点对比¶
特性 | 简单工厂模式 | 工厂方法模式 | 抽象工厂模式 |
---|---|---|---|
优点 | - 封装对象创建过程 - 简化客户端代码 - 集中管理对象创建 |
- 符合开闭原则 - 封装对象创建 - 提高代码复用性和可维护性 |
- 创建一系列相关对象 - 符合开闭原则 - 封装具体类 - 增强系统灵活性和可扩展性 |
缺点 | - 违反单一职责原则 - 增加系统复杂性 - 不易扩展 |
- 增加类的数量 - 结构复杂性 - 不适用于单一产品创建 |
- 增加类的数量 - 结构复杂性 - 不适用于单一产品创建 |
适用场景 | - 对象创建过程简单 - 产品类较少 - 需要通过参数创建对象 |
- 产品类较多或经常变化 - 需要通过子类工厂创建对象 |
- 需要创建一系列相关对象 - 需要确保产品族的兼容性 |
6. 选择合适的工厂模式¶
选择合适的工厂模式需要根据具体的需求和系统的复杂性来决定。以下是一些选择指南:
6.1. 使用简单工厂模式的情况¶
对象创建过程相对简单:对象的创建逻辑不复杂,不需要创建一系列相关的对象。
产品类较少且不易频繁变化:系统中产品类数量有限,且新增产品类的频率不高。
客户端仅需通过参数决定创建哪一种产品:不需要通过子类化来决定具体的产品类。
6.2. 使用工厂方法模式的情况¶
系统中产品类较多或经常变化:需要通过子类化来管理不同的产品类,便于扩展。
遵循开闭原则:希望通过新增子类来支持新的产品,而不修改已有代码。
需要通过子类工厂创建不同的产品:不同的工厂子类负责创建不同的产品类,实现职责分离。
6.3. 使用抽象工厂模式的情况¶
需要创建一系列相关或相互依赖的对象:确保产品族之间的兼容性,如UI组件(按钮、文本框、窗口等)。
系统需要独立于具体产品类的创建:客户端只依赖于抽象工厂和抽象产品接口,减少对具体类的依赖。
需要确保产品族的协同工作:通过同一个具体工厂创建的产品对象能够协同工作,符合设计的一致性。
7. 总结¶
工厂型设计模式通过不同的方式封装对象的创建过程,降低系统的耦合度,提升代码的可维护性和扩展性。以下是对简单工厂模式、工厂方法模式和抽象工厂模式的总结:
简单工厂模式:
特点:集中管理对象创建,通过参数决定具体产品类。
适用场景:对象创建过程简单,产品类较少且不易频繁变化。
优缺点:封装对象创建、简化客户端代码,但违反单一职责原则、不易扩展。
工厂方法模式:
特点:通过子类工厂决定具体产品类,实现工厂接口。
适用场景:产品类较多或经常变化,需符合开闭原则。
优缺点:符合开闭原则、封装对象创建,但增加类的数量、结构复杂。
抽象工厂模式:
特点:创建一系列相关对象,确保产品族的兼容性。
适用场景:需要创建相关或相互依赖的对象,确保产品族的一致性。
优缺点:创建一系列相关对象、符合开闭原则,但增加类的数量、结构复杂。