创建型设计模式-工厂模式(汇总)

169 阅读8分钟

工厂模式

工厂模式就是为了简化具体对象的创建的细节;

工厂模式简化图

                       +------------------+
                       |      Product     |
                       +------------------+
                       |   operation()    |
                       +------------------+
                                 ^
                                 |
                                 |
        +------------------------+------------------------+
        |                                                 |
+---------------------+                        +---------------------+
|   ConcreteProductA |                        |   ConcreteProductB |
+---------------------+                        +---------------------+
|    operation()     |                        |    operation()     |
+---------------------+                        +---------------------+
        ^                                                 ^
        |                                                 |
        +-------------------------------------------------+
                                 |
                                 |
                       +------------------+
                       |      Factory     |
                       +------------------+
                       | createProduct()  |
                       +------------------+

伪代码

  1. 定义协议(Protocol) :首先,定义一个协议,描述工厂所创建对象应该具有的属性和方法。
swift
Copy code
protocol Product {
    func operation()
}
  1. 实现具体产品类:创建遵循协议的具体产品类。
swift
Copy code
class ConcreteProductA: Product {
    func operation() {
        print("ConcreteProductA operation")
    }
}

class ConcreteProductB: Product {
    func operation() {
        print("ConcreteProductB operation")
    }
}
  1. 实现工厂类:创建一个工厂类,负责实例化具体产品对象。
swift
Copy code
class Factory {
    func createProduct(type: Int) -> Product {
        switch type {
        case 0:
            return ConcreteProductA()
        case 1:
            return ConcreteProductB()
        default:
            fatalError("Invalid product type")
        }
    }
}
  1. 使用工厂创建对象:在需要创建对象的地方,通过工厂类创建对象实例。
swift
Copy code
let factory = Factory()
let productA = factory.createProduct(type: 0)
let productB = factory.createProduct(type: 1)

productA.operation() // 输出:ConcreteProductA operation
productB.operation() // 输出:ConcreteProductB operation

通过工厂模式,我们可以将对象的创建逻辑与客户端代码分离,使得客户端不需要关心具体对象的创建细节,从而提高了代码的灵活性和可维护性。

特殊场景-产品不遵守统一的协议

# 定义产品类1
class Product1:
    def operation(self):
        print("Product 1 operation")

# 定义产品类2
class Product2:
    def operation(self):
        print("Product 2 operation")

# 工厂类
class Factory:
    def create_product(self, product_type):
        if product_type == "Product1":
            return Product1()
        elif product_type == "Product2":
            return Product2()
        else:
            raise ValueError("Invalid product type")

# 使用工厂创建产品并调用操作方法
factory = Factory()
product1 = factory.create_product("Product1")
product1.operation()

product2 = factory.create_product("Product2")
product2.operation()

高级用法-抽象工厂模式

伪代码

plaintext
Copy code
// 定义抽象工厂接口
interface AbstractFactory {
    createProductA(): AbstractProductA
    createProductB(): AbstractProductB
}

// 具体工厂类实现抽象工厂接口
class ConcreteFactory1 implements AbstractFactory {
    createProductA(): AbstractProductA {
        return new ConcreteProductA1()
    }
    
    createProductB(): AbstractProductB {
        return new ConcreteProductB1()
    }
}

class ConcreteFactory2 implements AbstractFactory {
    createProductA(): AbstractProductA {
        return new ConcreteProductA2()
    }
    
    createProductB(): AbstractProductB {
        return new ConcreteProductB2()
    }
}

// 定义抽象产品接口
interface AbstractProductA {
    methodA(): void
}

interface AbstractProductB {
    methodB(): void
}

// 具体产品类实现抽象产品接口
class ConcreteProductA1 implements AbstractProductA {
    methodA(): void {
        // 具体产品A1的方法实现
    }
}

class ConcreteProductA2 implements AbstractProductA {
    methodA(): void {
        // 具体产品A2的方法实现
    }
}

class ConcreteProductB1 implements AbstractProductB {
    methodB(): void {
        // 具体产品B1的方法实现
    }
}

class ConcreteProductB2 implements AbstractProductB {
    methodB(): void {
        // 具体产品B2的方法实现
    }
}

// 客户端代码使用抽象工厂和抽象产品
function clientCode(factory: AbstractFactory) {
    let productA = factory.createProductA()
    let productB = factory.createProductB()
    
    // 使用产品A和产品B
    productA.methodA()
    productB.methodB()
}

// 使用具体工厂创建产品
let factory1 = new ConcreteFactory1()
clientCode(factory1)

let factory2 = new ConcreteFactory2()
clientCode(factory2)

在上面的示例中,抽象工厂接口定义了创建一组相关产品的方法。具体工厂类实现了抽象工厂接口,每个具体工厂负责创建一组具体产品。抽象产品接口定义了产品的通用方法,而具体产品类实现了具体的产品功能。客户端代码通过传入具体工厂对象来创建和使用一组相关产品。

举例:alamofire库执行器的设计

// 定义抽象请求协议
protocol Request {
    // 发起请求的方法
    func send() -> Response
}

// 定义具体请求对象
class URLRequest: Request {
    func send() -> Response {
        // 使用 URLSession 发起网络请求,并返回响应结果
    }
}

// 定义抽象请求执行器协议
protocol SessionDelegate {
    // 发起请求的方法,接收抽象请求对象,并返回响应结果
    func sendRequest(request: Request) -> Response
}

// 定义具体的请求执行器
class URLSessionDelegate: SessionDelegate {
    func sendRequest(request: Request) -> Response {
        // 实现具体的网络请求逻辑,使用 URLRequest 发起网络请求,并返回响应结果
    }
}

// 定义抽象工厂协议
protocol SessionFactory {
    // 创建具体请求执行器的方法
    func makeSessionDelegate() -> SessionDelegate
}

// 定义具体的工厂,用于创建 URLSessionDelegate
class URLSessionFactory: SessionFactory {
    func makeSessionDelegate() -> SessionDelegate {
        return URLSessionDelegate()
    }
}

// 客户端代码使用抽象工厂创建请求执行器,并发送请求
class Client {
    let sessionFactory: SessionFactory
    
    init(factory: SessionFactory) {
        self.sessionFactory = factory
    }
    
    func sendRequest() {
        // 使用工厂创建请求执行器
        let sessionDelegate = sessionFactory.makeSessionDelegate()
        
        // 使用请求执行器发送请求
        let request = URLRequest()
        let response = sessionDelegate.sendRequest(request: request)
        
        // 处理响应结果
        // ...
    }
}

// 使用 Alamofire 的示例
let urlSessionFactory = URLSessionFactory()
let client = Client(factory: urlSessionFactory)
client.sendRequest()

以上伪代码简要展示了Alamofire库中抽象工厂模式的实现思路。Alamofire通过抽象请求对象、抽象请求执行器和工厂接口的定义,实现了一种灵活的网络请求管理机制,使得用户可以轻松地定制和切换不同的网络请求执行器,而无需修改大量的客户端代码。

高级用法-工厂方法模式

伪代码

// 定义产品接口
interface Product {
    method operation() -> void
}

// 具体产品类 A
class ConcreteProductA implements Product {
    method operation() -> void {
        // 实现具体产品 A 的操作
    }
}

// 具体产品类 B
class ConcreteProductB implements Product {
    method operation() -> void {
        // 实现具体产品 B 的操作
    }
}

// 定义工厂接口
interface Factory {
    method createProduct() -> Product
}

// 具体工厂 A,用于创建产品 A
class ConcreteFactoryA implements Factory {
    method createProduct() -> Product {
        return new ConcreteProductA()
    }
}

// 具体工厂 B,用于创建产品 B
class ConcreteFactoryB implements Factory {
    method createProduct() -> Product {
        return new ConcreteProductB()
    }
}

// 客户端代码
class Client {
    property factory: Factory
    
    constructor(factory: Factory) {
        this.factory = factory
    }
    
    method run() -> void {
        // 使用工厂创建产品对象
        product = factory.createProduct()
        
        // 调用产品的方法
        product.operation()
    }
}

// 使用工厂方法模式创建产品 A 的客户端
factoryA = new ConcreteFactoryA()
clientA = new Client(factoryA)
clientA.run()

// 使用工厂方法模式创建产品 B 的客户端
factoryB = new ConcreteFactoryB()
clientB = new Client(factoryB)
clientB.run()

在这个示例中,工厂方法模式允许客户端使用一个通用的接口来创建产品,而具体的产品类型由具体的工厂子类来决定。这样一来,客户端代码与具体产品类之间的耦合性降低了,同时也便于扩展和维护。

举例:cocoa库NSNumber的设计

// 工厂方法模式示例:NSNumber

// 定义工厂接口
@protocol NumberFactory <NSObject>
- (NSNumber *)createNumberWithValue:(NSNumber *)value;
@end

// 具体工厂实现整数工厂
@interface IntegerFactory : NSObject <NumberFactory>
@end

@implementation IntegerFactory
- (NSNumber *)createNumberWithValue:(NSNumber *)value {
    return [NSNumber numberWithInt:[value intValue]];
}
@end

// 具体工厂实现浮点数工厂
@interface FloatFactory : NSObject <NumberFactory>
@end

@implementation FloatFactory
- (NSNumber *)createNumberWithValue:(NSNumber *)value {
    return [NSNumber numberWithFloat:[value floatValue]];
}
@end

// 客户端代码
NSNumber *value = @3.14;
id<NumberFactory> factory = [FloatFactory new];
NSNumber *number = [factory createNumberWithValue:value];

在上面的伪代码中,我们定义了一个 NumberFactory 接口,并创建了两个具体工厂类 IntegerFactoryFloatFactory。每个工厂类都实现了 createNumberWithValue: 方法来根据传入的值创建对应的 NSNumber 对象。客户端根据需要选择合适的工厂对象,并使用工厂对象来创建 NSNumber 对象。

高级用法-延迟初始化

高级用法-单例工厂模式

伪代码

工厂单例模式是一种设计模式,结合了工厂模式和单例模式的特点。它的目的是确保在整个应用程序中只有一个工厂实例,并且该工厂负责创建其他类的实例。

下面是工厂单例模式的伪代码示例:

plaintext
Copy code
// 工厂类,负责创建其他类的实例并确保只有一个工厂实例存在
class SingletonFactory {
    private static SingletonFactory instance;
    
    // 私有构造函数,防止外部创建新实例
    private SingletonFactory() {}
    
    // 静态方法获取工厂实例
    public static SingletonFactory getInstance() {
        if (instance == null) {
            instance = new SingletonFactory();
        }
        return instance;
    }
    
    // 创建其他类的实例的方法
    public SomeClass createInstance() {
        return new SomeClass();
    }
}

// 其他类的示例
class SomeClass {
    // 一些属性和方法
}

// 客户端代码
class Client {
    public static void main() {
        // 获取工厂实例
        SingletonFactory factory = SingletonFactory.getInstance();
        
        // 使用工厂实例创建其他类的实例
        SomeClass instance = factory.createInstance();
        
        // 使用创建的实例
        instance.doSomething();
    }
}

在上面的示例中,SingletonFactory 是工厂单例模式的实现。它使用了单例模式确保只有一个工厂实例存在,并且提供了创建其他类实例的方法。客户端可以通过 getInstance() 方法获取工厂实例,并使用该实例创建其他类的实例。

其他

分析 抽象工厂模式和工厂方法模式 的区别

  1. 工厂方法模式

    工厂只能创建单一的产品

    • 定义了一个接口或抽象类,该接口或抽象类负责创建产品对象。
    • 具体的工厂类实现了该接口或抽象类,并负责创建具体的产品对象。
    • 每个具体工厂类只能创建一种类型的产品。
  2. 抽象工厂模式

    工厂可以创建一组产品

    • 定义了一个接口或抽象类,该接口或抽象类声明了一组创建相关或依赖对象的方法。
    • 具体的工厂类实现了该接口或抽象类,并负责创建一组相关的产品对象。
    • 每个具体工厂类可以创建一组相关的产品,而不仅限于单一类型的产品。

工厂和产品是否必须要遵守抽象的接口

非必需,但是把工厂、产品设计一个接口层,有利于后续拓展;建议设计一个抽象的接口;

工厂单例模式和单例模式的区别

不完全一样。虽然它们都涉及到创建单个实例,但它们的重点不同。

  • 工厂单例模式(Factory Singleton Pattern) :这种模式结合了工厂模式和单例模式的特点。它包括一个工厂类,用于创建单例对象,并确保在应用程序中只存在一个实例。工厂单例模式将创建和管理单例对象的逻辑委托给一个工厂类,使得整个系统更加灵活和可扩展。
  • 单例模式(Singleton Pattern) :单例模式是一种创建型设计模式,用于确保类只有一个实例,并提供一个全局访问点来访问该实例。它通常通过将类的构造函数设为私有,并提供一个静态方法来返回该类的唯一实例来实现。

虽然工厂单例模式可以使用单例模式来确保工厂类只有一个实例,但它们并不是同一概念。工厂单例模式的重点在于创建和管理对象实例,而单例模式的重点在于确保类只有一个实例。