建造者模式
一 场景
在软件开发中,我们有时候会创建一些复杂的对象,这些对象有着复杂的内部结构,它们都是有一系列部件组成。这些部件相互依赖,而且部件的构建通常面临着复杂的变化。我们需要先按照一定的顺序来创建各个部件,最后将这些部件组装成一个完整的对象。
针对上述情况,我们可以使用建造者模式来创建对象。建造者模式可以让创建对象的算法独立于对象的组成部分以及装配方式。
二 定义
建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。
三 类图
Builder ***(抽象建造者):***Builder抽象建造者既可以是抽象类,也可以是接口。抽象建造者中一般是定义了两类方法。一类是声明了创建复杂对象各个部件的方法。另一类声明了专门用于返回复杂对象的方法。

ConcreteBuilder ***(具体建造者):***具体建造者类是抽象建造者的具体实现类。它主要了实现了复杂产品各个部件的具体构造和装配方法。具体建造者还会定义和明确它所创建的复杂对象,并将创建好的产品返回。

Director ***(指挥者类):***指挥者类一般是用于定义复杂对象部件的建造次序。指挥者类会引用一个抽象建造者。指挥者类在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。

在有些情况下,为了简化代码。我们可以省略指挥者类。将指挥者类Director和抽象建造者类Builder合并,在Builder中提供逐步构建复杂产品对象的方法。

Product ***(产品类):***产品类就是我们要构建的复杂对象,它一般包含了多个组成部件。

四 代码示例
我们可能会自己组装电脑主机。电脑主机是有cpu,内存,主板,硬盘,机箱等组成。我们自己组装电脑主机的话,可以在电脑城或者网上依次购买cpu,内存,主板,硬盘,机箱这些部件。只要确保这些部件的型号是兼容的,再把它们组装到一起就变成了电脑主机。
一般电脑主机使用场景的不同,我们对其配置的要求也是不同的。如果平时在家里就上上网的电脑,配置就可以低一些。而在工作中使用的电脑,配置就要高一些。
针对组装电脑主机的这种情景,我就可以使用建造者模式来进行设计。
我们定义一个Computer类来表示电脑主机的产品类,在Computer类中定义了cpu,内存,主板,硬盘,机箱这些属性。

我们定义了一个抽象建造者类AbstractComputerBuilder。在AbstractComputerBuilder类中,定义了一个Computer类型的产品对象。然后再声明了建造组成电脑主机各个部件的虚方法。最后再定义了getComputer方法来返回组装完毕的电脑主机。

我们定义了一个HomeComputerBuilder具体建造者类,来组装配置低的家庭电脑。在HomeComputerBuilder类中,都覆写了父类AbstractComputerBuilder中定义的建造各个部件的虚方法。例如:家庭电脑配置要求低一些,所以cpu是4核,内层只有8G等。

同理我们又定义了一个WorkComputerBuilder具体建造者类,来组装配置要求高的工作电脑。例如:工作电脑配置要求高,所以cpu是12核的,内层需要32G。

最后定义了指挥者ComputerDirector类。在ComputerDirector类定义了一个抽象建造者类AbstractComputerBuilder。指挥者使用该抽象类来引用一个具体建造者类。
在constructComputer方法中,程序会按照一定的顺序,依次调用建造者类中构建电脑主机各个部件的方法,最后将组装好的主机返回。

运行示例

运行结果

五 总结
建造者模式是一种创建型模式。它主要用于一些复杂对象的创建。建造者模式使得对象的建造与表示分离。客户端不需要知道产品的具体构建细节,就可以使用相同的创建过程得到不同的产品。
优点:
- 建造者模式复杂产品的创建步骤分解在不同的部件方法中,可以更加精细地控制产品的创建,使得创建过程非常清晰。
- 建造者模式将产品的建造和表示分离,实现了解耦,可以使用相同的创建过程得到不同的产品。
- 增加新的具体建造者无需修改原有代码,系统易于扩展,符合"开闭原则"。
缺点:
- 如果产品的内部变化复杂,建造者模式就需要定义很多具体建造者类来实现这种变化。这样可能导致系统变得庞大,增加系统的维护成本。
建造者模式与工厂模式的区别:
建造者模式和工厂模式有许多相似的地方。它们都属于对象创建型模式,都是用来创建对象的。那它们的区别主要在哪里呢?
建造者模式和工厂模式主要区别是创建对象的粒度和复杂度不同。
工厂模式只关心产品的整体,而建造者模式注重的是产品中各个部件构建的过程,以及这些部件的装配顺序。建造者模式是通过一步一步地部件的生产,精确构造创建出一个复杂的对象。就像工厂里生产机器,先生产出一个个零件,再把这些零件按顺序组装成一个机器。
以本文中组装电脑主机为例,工厂模式的话,就是生产工作电脑和家庭电脑两种产品。而建造者模式的话,则关注电脑主机中,cpu,主板,内存,硬盘等这些部件的生产,通过生产出这些不同的部件,最后按一定顺序来组装成工作电脑和家庭电脑这两种不同的产品。