建造者模式

114 阅读3分钟

建造者模式(Builder Pattern)又叫生成器模式,有点类似工厂模式,两者都是用专门的类来实现对象的创建。

  • 工厂模式用来创建一系列相关类型但不同的对象。
  • 建造者模式则用来创建一种类型的复杂对象,通过设置不同的可选参数,定制化创建不同对象。

主要区别是建造者模式着重一步步构造一个复杂对象,而抽象工厂模式着重于多个系列的产品对象。

为什么使用建造者模式

  • 一个类有很多属性,构造函数和参数过于长。
  • 属性之间有一定的依赖和约束关系。
  • 对象的创建需要遵循一定的顺序或者步骤

有一句话对建造者模式总结的很好:

当我们想要创建一个由多个部分构成的对象,而且他们的构建需要一步接一步的地完成,只有当各个部分都创建好,这个对象才算完整。

这正是 建造者设计模式的用武之地。

建造者模式的优缺点

优点

  1. 建造者独立,易扩展。
  2. 便于控制细节风险。
  3. 将对象的构造与表现解耦

缺点

  1. 产品必须有共同点,范围有限制。
  2. 如果内部变化复杂,会有很多的建造类。

建造者模式的构成

  1. 实际对象:实际要返回的对象
  2. 建造者抽象类:定义建造者实体类需要实现的功能。
  3. 建造者实体类:继承建造者抽象类,具体实现抽象类方法。
  4. 指挥者类:用来控制建造者内部构建的顺序及流程。

应用场景

最常用的一个场景就是操作数据库的 ORM。回想一下,ORM 中一个很重要的概念:延迟加载,其实就是建造者模式最常见的应用。

下面通过一个生产手机的例子来了解一下建造者模式的各个构成部分。

实际对象

要生产一台手机,基本的组件有《屏幕、电池、cpu》,我们的手机对象定义如下:

class Phone:
    def __init__(self, screen=None, battery=None, cpu=None):
        self.screen = screen
        self.battery = battery
        self.cpu = cpu

    def __repr__(self):
        return f"A phone with {self.screen} / {self.battery} / {self.cpu}"

建造者抽象类

定义建造者实体类需要实现的功能,需要实现生产屏幕、电池、cpu的功能

class PhoneBuilder(ABC):
    phone = Phone()

    @abstractmethod
    def build_screen(self):
        pass

    @abstractmethod
    def build_battery(self):
        pass

    @abstractmethod
    def build_cpu(self):
        pass

建造者实现类

继承建造者抽象类,具体实现抽象类方法

# 实现一个华为手机和苹果手机的建造者实现类

class IphoneBuilder(PhoneBuilder):
    def build_screen(self):
        self.phone.screen = "三星屏幕"

    def build_battery(self):
        self.phone.battery = "苹果电池"

    def build_cpu(self):
        self.phone.cpu = "A15芯片"


class HuaweiPhoneBuilder(PhoneBuilder):
    def build_screen(self):
        self.phone.screen = "京东方屏幕"

    def build_battery(self):
        self.phone.battery = "华为电池"

    def build_cpu(self):
        self.phone.cpu = "麒麟990芯片"

指挥者

用来控制建造者内部构建的顺序及流程

class Make:
    def __init__(self):
        pass

    @staticmethod
    def build(builder: PhoneBuilder):
        """
        必须满足先组装cpu,再到电池,再到屏幕这样的顺序
        """
        builder.build_cpu()
        builder.build_battery()
        builder.build_screen()
        print(builder.phone)
        return

# A phone with 三星屏幕 / 苹果电池 / A15芯片
Make.build(IphoneBuilder())
# A phone with 京东方屏幕 / 华为电池 / 麒麟990芯片
Make.build(HuaweiPhoneBuilder())

总结

建造者模式能够帮我们一步步定制化实现复杂对象的创建,并将对象的创建和使用解耦,在很多场景下都有应用。