【软件设计】常用设计模式--工厂模式
软件设计模式(二)
- 一、工厂模式(Factory Pattern)
- 1. 概念
- 2. 工厂模式的类型
- 3. 实现方式
- (1)简单工厂模式
- C# 实现
- Java 实现
- (2)工厂方法模式
- C# 实现
- Java 实现
- (3)抽象工厂模式
- C# 实现
- Java 实现
- 4. 优点
- 5. 缺点
- 6. 适用场景
- 小结
- 二、工厂模式变体
- 1. 简单工厂模式的变体
- 变体1: 参数化工厂
- C# 示例
- 变体2: 反射工厂
- C# 示例
- 2. 工厂方法模式的变体
- 变体1: 可配置工厂
- C# 示例
- 变体2: 延迟初始化
- C# 示例
- 3. 抽象工厂模式的变体
- 变体1: 层次结构的抽象工厂
- C#示例
- 变体2: 工厂生产线
- C#示例
- 4. 实际应用场景
- 场景1: 数据库连接管理
- C#示例
- 场景2: GUI 元素创建
- C#示例
- 场景3: 日志系统
- C#示例
- 小结
一、工厂模式(Factory Pattern)
1. 概念
工厂模式通过定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂模式让一个类的实例化延迟到子类进行,从而实现代码的松耦合和扩展性。
2. 工厂模式的类型
工厂模式有几种不同的实现方式:
- 简单工厂模式(Simple Factory): 使用一个工厂类根据传递的参数决定创建哪个具体类的实例。
- 工厂方法模式(Factory Method): 定义一个创建对象的接口,让子类决定具体实例化哪个类。
- 抽象工厂模式(Abstract Factory): 提供一个接口,用于创建一系列相关或互相依赖的对象,而无需指定它们具体的类。
3. 实现方式
我们先从最基础的简单工厂模式开始,然后逐步介绍工厂方法模式和抽象工厂模式。
(1)简单工厂模式
简单工厂模式通常使用一个静态方法来根据传入的参数创建不同的对象。
C# 实现
public abstract class Product
{
public abstract void DoSomething();
}
public class ConcreteProductA : Product
{
public override void DoSomething()
{
Console.WriteLine("Product A is doing something.");
}
}
public class ConcreteProductB : Product
{
public override void DoSomething()
{
Console.WriteLine("Product B is doing something.");
}
}
public class ProductFactory
{
public static Product CreateProduct(string type)
{
switch (type)
{
case "A":
return new ConcreteProductA();
case "B":
return new ConcreteProductB();
default:
throw new ArgumentException("Invalid product type.");
}
}
}
- 使用方法:
Product product = ProductFactory.CreateProduct("A");
Java 实现
abstract class Product {
abstract void doSomething();
}
class ConcreteProductA extends Product {
@Override
void doSomething() {
System.out.println("Product A is doing something.");
}
}
class ConcreteProductB extends Product {
@Override
void doSomething() {
System.out.println("Product B is doing something.");
}
}
class ProductFactory {
public static Product createProduct(String type) {
switch (type) {
case "A":
return new ConcreteProductA();
case "B":
return new ConcreteProductB();
default:
throw new IllegalArgumentException("Invalid product type.");
}
}
}
使用方法: Product product = ProductFactory.createProduct("A");
(2)工厂方法模式
在工厂方法模式中,创建对象的逻辑被推迟到子类中,而不是集中在一个工厂类中。
C# 实现
public abstract class Product
{
public abstract void DoSomething();
}
public class ConcreteProductA : Product
{
public override void DoSomething()
{
Console.WriteLine("Product A is doing something.");
}
}
public class ConcreteProductB : Product
{
public override void DoSomething()
{
Console.WriteLine("Product B is doing something.");
}
}
public abstract class Creator
{
public abstract Product FactoryMethod();
public void AnOperation()
{
var product = FactoryMethod();
product.DoSomething();
}
}
public class ConcreteCreatorA : Creator
{
public override Product FactoryMethod()
{
return new ConcreteProductA();
}
}
public class ConcreteCreatorB : Creator
{
public override Product FactoryMethod()
{
return new ConcreteProductB();
}
}
使用方法:
Creator creator = new ConcreteCreatorA();
creator.AnOperation();
Java 实现
abstract class Product {
abstract void doSomething();
}
class ConcreteProductA extends Product {
@Override
void doSomething() {
System.out.println("Product A is doing something.");
}
}
class ConcreteProductB extends Product {
@Override
void doSomething() {
System.out.println("Product B is doing something.");
}
}
abstract class Creator {
public abstract Product factoryMethod();
public void anOperation() {
Product product = factoryMethod();
product.doSomething();
}
}
class ConcreteCreatorA extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductA();
}
}
class ConcreteCreatorB extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductB();
}
}
使用方法:
Creator creator = new ConcreteCreatorA();
creator.anOperation();
(3)抽象工厂模式
抽象工厂模式通过为一系列相关或依赖的对象提供一个创建接口,使得客户端可以不必指定具体的类名,就可以创建对象族。
C# 实现
public abstract class ProductA { }
public abstract class ProductB { }
public class ConcreteProductA1 : ProductA { }
public class ConcreteProductA2 : ProductA { }
public class ConcreteProductB1 : ProductB { }
public class ConcreteProductB2 : ProductB { }
public abstract class AbstractFactory
{
public abstract ProductA CreateProductA();
public abstract ProductB CreateProductB();
}
public class ConcreteFactory1 : AbstractFactory
{
public override ProductA CreateProductA() => new ConcreteProductA1();
public override ProductB CreateProductB() => new ConcreteProductB1();
}
public class ConcreteFactory2 : AbstractFactory
{
public override ProductA CreateProductA() => new ConcreteProductA2();
public override ProductB CreateProductB() => new ConcreteProductB2();
}
使用方法:
AbstractFactory factory = new ConcreteFactory1();
ProductA productA = factory.CreateProductA();
ProductB productB = factory.CreateProductB();
Java 实现
abstract class ProductA { }
abstract class ProductB { }
class ConcreteProductA1 extends ProductA { }
class ConcreteProductA2 extends ProductA { }
class ConcreteProductB1 extends ProductB { }
class ConcreteProductB2 extends ProductB { }
abstract class AbstractFactory {
abstract ProductA createProductA();
abstract ProductB createProductB();
}
class ConcreteFactory1 extends AbstractFactory {
@Override
ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
ProductB createProductB() {
return new ConcreteProductB1();
}
}
class ConcreteFactory2 extends AbstractFactory {
@Override
ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
ProductB createProductB() {
return new ConcreteProductB2();
}
}
使用方法:
AbstractFactory factory = new ConcreteFactory1();
ProductA productA = factory.createProductA();
ProductB productB = factory.createProductB();
4. 优点
- 解耦创建和使用: 客户端代码不直接依赖于具体产品类,降低了代码的耦合度。
- 可扩展性强: 新的产品可以通过增加新的工厂类或方法实现,而不需要修改现有代码。
5. 缺点
- 增加复杂性: 引入工厂模式可能会增加系统的复杂性,特别是在简单对象创建的场景中。
- 抽象工厂的维护: 随着产品族的增加,抽象工厂模式可能会导致过多的类和接口。
6. 适用场景
- 对象创建过程复杂: 适用于需要复杂对象创建过程的场景,如多个依赖对象的创建、对象的条件创建等。
- 系统解耦: 需要将对象的创建和使用解耦的场景,如插件系统、依赖注入等。
小结
工厂模式在创建对象时提供了灵活性和可扩展性。经过上面的学习,不难发现,从简单工厂模式到工厂模式,再到抽象工厂模式,实际就是对软件架构进一步解耦的过程,提高代码的扩展性,也使得软件架构能够更加的灵活。
二、工厂模式变体
1. 简单工厂模式的变体
虽然简单工厂模式是最基础的,但在某些情况下,我们可以通过参数化或动态生成对象来增强它的功能。
变体1: 参数化工厂
在这个变体中,工厂方法接受不同的参数类型,不仅仅是一个标识符字符串,还可以是枚举、配置对象或条件判断等。
C# 示例
public enum ProductType
{
ProductA,
ProductB
}
public class ProductFactory
{
public static Product CreateProduct(ProductType type)
{
switch (type)
{
case ProductType.ProductA:
return new ConcreteProductA();
case ProductType.ProductB:
return new ConcreteProductB();
default:
throw new ArgumentException("Invalid product type.");
}
}
}
变体2: 反射工厂
可以通过反射来动态创建对象,从而减少分支逻辑的硬编码。
C# 示例
public class ProductFactory
{
public static Product CreateProduct(string className)
{
Type type = Type.GetType(className);
return (Product)Activator.CreateInstance(type);
}
}
这种方法可以在运行时通过类的名称或其他元数据信息来创建对象,适合大型系统中的动态扩展需求。
2. 工厂方法模式的变体
工厂方法模式可以根据不同的扩展需求进行调整,通常适合创建复杂对象时使用。下面是一些变体:
变体1: 可配置工厂
工厂方法可以通过读取配置文件或外部资源来确定创建的对象类型。比如在Web开发中,可以通过读取XML或JSON文件来动态配置具体类的选择。
C# 示例
public class ConfigurableProductFactory : Creator
{
public override Product FactoryMethod()
{
string type = ConfigurationManager.AppSettings["ProductType"];
if (type == "A")
return new ConcreteProductA();
else
return new ConcreteProductB();
}
}
变体2: 延迟初始化
有时候我们需要延迟创建对象,以便减少内存占用或提高启动速度。可以结合工厂模式和延迟加载模式来实现这种需求。
C# 示例
public class LazyProductFactory : Creator
{
private Product _product;
public override Product FactoryMethod()
{
if (_product == null)
{
_product = new ConcreteProductA(); // 延迟创建对象
}
return _product;
}
}
3. 抽象工厂模式的变体
抽象工厂模式是工厂模式的进一步抽象,可以为对象族创建工厂。通常用于需要创建多个相关对象时,但在实际应用中,可以进一步优化和扩展。
变体1: 层次结构的抽象工厂
在复杂的系统中,抽象工厂可以为不同的产品层次结构创建工厂。比如,一个GUI系统可能有不同的控件类型,每种控件类型都有对应的工厂。
C#示例
// 抽象工厂为不同控件创建工厂
public abstract class GUIFactory
{
public abstract Button CreateButton();
public abstract Checkbox CreateCheckbox();
}
// Windows 工厂
public class WindowsFactory : GUIFactory
{
public override Button CreateButton() => new WindowsButton();
public override Checkbox CreateCheckbox() => new WindowsCheckbox();
}
// Mac 工厂
public class MacFactory : GUIFactory
{
public override Button CreateButton() => new MacButton();
public override Checkbox CreateCheckbox() => new MacCheckbox();
}
这种层次结构的抽象工厂使得我们可以轻松扩展支持新的操作系统或设备。
变体2: 工厂生产线
在某些复杂应用中,抽象工厂不仅仅用于创建单个对象,而是用于创建一组相关的对象。比如在游戏开发中,工厂可以创建整个生态系统的对象,如玩家角色、敌人、道具等。
C#示例
public abstract class GameFactory
{
public abstract Player CreatePlayer();
public abstract Enemy CreateEnemy();
public abstract Item CreateItem();
}
4. 实际应用场景
场景1: 数据库连接管理
工厂模式可以用于管理数据库连接。例如,不同的数据库(如SQL Server、MySQL、Oracle)可以通过工厂模式进行选择,实现不同数据库的连接对象。
C#示例
public abstract class DatabaseConnectionFactory
{
public abstract IDbConnection CreateConnection();
}
public class SqlServerConnectionFactory : DatabaseConnectionFactory
{
public override IDbConnection CreateConnection()
{
return new SqlConnection();
}
}
public class MySqlConnectionFactory : DatabaseConnectionFactory
{
public override IDbConnection CreateConnection()
{
return new MySqlConnection();
}
}
客户端代码可以动态决定使用哪种数据库,而不需要知道具体的实现。
场景2: GUI 元素创建
GUI系统中,控件类型众多且随平台不同。通过工厂模式,可以轻松支持不同平台的控件,如Windows和Mac的按钮、文本框等。
C#示例
GUIFactory factory = new WindowsFactory();
Button button = factory.CreateButton();
Checkbox checkbox = factory.CreateCheckbox();
场景3: 日志系统
工厂模式可以根据配置文件或运行时参数决定使用哪种日志记录系统,比如文件日志、数据库日志、远程日志等。
C#示例
public abstract class LoggerFactory
{
public abstract ILogger CreateLogger();
}
public class FileLoggerFactory : LoggerFactory
{
public override ILogger CreateLogger()
{
return new FileLogger();
}
}
小结
工厂模式的变体和应用场景非常广泛,无论是在对象创建、系统解耦还是灵活扩展中都能提供极大的便利。不同场景可以根据需求选择不同的工厂模式变体,如动态对象创建、延迟加载、配置驱动等。通过结合工厂模式与其他设计模式(如策略模式、装饰器模式等),可以实现更加灵活和可维护的架构。