漫谈设计模式 [2]:工厂方法模式

发布于:2024-09-18 ⋅ 阅读:(62) ⋅ 点赞:(0)

引导性开场

菜鸟:老鸟,我在项目中遇到一个问题。每当需要创建对象时,我都直接使用类的构造函数,但随着项目复杂度的增加,这种方法变得越来越不可维护。你有什么建议吗?

老鸟:你提到的问题很常见。直接使用构造函数在简单场景下还行,但在复杂项目中会导致代码耦合度高、维护困难。你听说过工厂方法模式吗?

菜鸟:工厂方法模式?好像听过,但不太了解具体是什么。

渐进式介绍概念

老鸟:简单来说,工厂方法模式是一种创建对象的设计模式。它将对象的创建过程封装在一个工厂类中,而不是在代码中直接使用构造函数。举个生活中的例子,想象你去了一家餐馆点餐。你不会亲自去厨房做饭,而是告诉服务员你要什么,然后服务员帮你把饭菜准备好。这就类似于工厂方法模式。

菜鸟:哦,有点明白了。也就是说,工厂方法模式可以帮我们把对象的创建过程封装起来,对吧?

老鸟:没错!它的核心思想就是将对象的创建延迟到子类中,让子类决定要创建的对象类型。

Python代码示例,逐步展开

菜鸟:那我们用代码来看看吧。

老鸟:好的,先从一个简单的例子开始。假设我们有一个 Product 类和它的两个子类 ConcreteProductAConcreteProductB

class Product:
    def operation(self):
        pass

class ConcreteProductA(Product):
    def operation(self):
        return "Result of ConcreteProductA"

class ConcreteProductB(Product):
    def operation(self):
        return "Result of ConcreteProductB"

菜鸟:看起来很简单。那我们怎么用工厂方法模式来创建这些对象呢?

老鸟:首先,我们定义一个工厂基类 Creator,它有一个创建产品的方法 create_product。然后,我们定义具体的工厂子类 ConcreteCreatorAConcreteCreatorB,它们分别创建 ConcreteProductAConcreteProductB

class Creator:
    def create_product(self):
        pass

class ConcreteCreatorA(Creator):
    def create_product(self):
        return ConcreteProductA()

class ConcreteCreatorB(Creator):
    def create_product(self):
        return ConcreteProductB()

菜鸟:哦,我明白了。这样我们就可以通过工厂子类来创建不同的产品对象了。

老鸟:没错。来看看完整的例子。

# 产品类及其子类
class Product:
    def operation(self):
        pass

class ConcreteProductA(Product):
    def operation(self):
        return "Result of ConcreteProductA"

class ConcreteProductB(Product):
    def operation(self):
        return "Result of ConcreteProductB"

# 工厂基类及其子类
class Creator:
    def create_product(self):
        pass

class ConcreteCreatorA(Creator):
    def create_product(self):
        return ConcreteProductA()

class ConcreteCreatorB(Creator):
    def create_product(self):
        return ConcreteProductB()

# 客户端代码
def client_code(creator: Creator):
    product = creator.create_product()
    print(f"Client: {product.operation()}")

if __name__ == "__main__":
    print("App: Launched with ConcreteCreatorA.")
    client_code(ConcreteCreatorA())

    print("App: Launched with ConcreteCreatorB.")
    client_code(ConcreteCreatorB())

菜鸟:这很有趣。但是,直接实例化工厂子类和直接使用构造函数有何区别呢?

问题与反思

老鸟:这是个好问题。直接使用构造函数时,客户端代码依赖于具体类,这会导致代码耦合度高。而使用工厂方法模式,客户端代码依赖于抽象的工厂类,具体的产品创建逻辑被封装在工厂子类中,这样可以降低代码的耦合度,提高可维护性。

菜鸟:明白了。这样当我们需要添加新产品时,只需要添加新的工厂子类和产品子类,而无需修改客户端代码。

老鸟:正是如此。

优势与适用场景

老鸟:工厂方法模式的优势在于:

  1. 降低耦合度:客户端代码依赖于抽象的工厂类,而不是具体的产品类。
  2. 提高可扩展性:添加新产品时,只需要添加新的工厂子类和产品子类,无需修改现有代码。
  3. 遵循开闭原则:扩展新的功能时,不需要修改现有代码,减少了错误风险。

菜鸟:那它适用于哪些场景呢?

老鸟:工厂方法模式适用于以下场景:

  1. 当一个类不知道它所需要的对象的类时
  2. 当一个类希望由其子类来指定创建的对象时
  3. 当类将创建对象的职责委托给多个帮助子类中的某一个时,并希望将哪一个子类是代理者这一信息局部化时

常见误区与优化建议

老鸟:不过,使用工厂方法模式时也要注意一些常见误区:

  1. 滥用模式:工厂方法模式适用于特定场景,不要为了使用而使用。
  2. 复杂性增加:对于简单对象创建,不必使用工厂方法模式,避免不必要的复杂性。

菜鸟:明白了,那有没有什么优化建议呢?

老鸟:优化建议包括:

  1. 明确需求:在决定使用工厂方法模式前,明确你的需求和问题。
  2. 结合其他模式:有时可以结合其他设计模式,如抽象工厂模式来进一步优化设计。

总结与延伸阅读

老鸟:今天我们讨论了工厂方法模式,包括它的定义、优势、适用场景以及常见误区。希望通过这些内容,你对工厂方法模式有了更深的理解。

菜鸟:非常感谢,老鸟!我学到了很多。

老鸟:不客气。如果你感兴趣,接下来可以学习一下其他设计模式,如单例模式和抽象工厂模式。推荐阅读《设计模式:可复用面向对象软件的基础》这本书,对理解设计模式非常有帮助。

菜鸟:好的,我会去看看这本书。谢谢你的指导!

老鸟:祝你学习愉快!