建造者模式是非常常用的设计模式,顾名思义,该模式主要一个对象。builder的意思是建造者或者建筑工人,想到建造者自然会想到楼房。楼房是千差万别 的,楼房的外形、层数、内部房间的数量、房间的装饰等等,但是对于建造者来说,抽象出来的建筑流程是确定的。建筑一座楼房,首先需要打桩、建立基础,然后 建立框架。建造者模式最为重要的是流程是不变的,每个流程实现的具体细节则是经常变化的。
      建造者模式保证了流程不会变化,流程即不会增加、也不会遗漏或者产生流程次序错误,这是非常重要的。我们熟知的楼歪歪事件,官方的解释就是由于先建立楼房后,再建设停车场造成的,这是典型的建造次序错乱。
      其实在编程实践中,建造者模式比比皆是。
      比如文件操作,包括打开、读写文件和关闭三个步骤,无论是二进制文件、文本文件、TDMS 文件都必须遵循这个流程。其实、打开、读写、关闭并不仅限于文件,串口操作、GPIB等等,都遵循着同样的流程,不过是每个流程的实现细节不同。
      任何人的成长过程也是一个典型的建造者模式,都包括婴儿阶段、少年儿童阶段、青年阶段、中年阶段和老年阶段。每个人在各自阶段成长的结果是各自不同的,但是整个成长过程肯定是确定不变的,不可能出现先老年、后儿童的情形。
      我们看看建造模式的定义。

Builder模式的缘起:
      假设创建游戏中的一个房屋House设施,该房屋的构建由几部分组成,且各个部分富于变化。如果使用最直观的设计方法,每一个房屋部分的变化,都将导致房屋构建的重新修正.....

动机(Motivation):
      在软件系统中,有时候面临一个"复杂对象"的创建工作,其通常由各个部分的子对象用一定算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合到一起的算法却相对稳定
      如何应对种变化呢?如何提供一种"封装机制"来隔离出"复杂对象的各个部分"的变化,从而保持系统中的"稳定构建算法"不随需求的改变而改变?

意图(Intent):
      将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示
                                                              -------《设计模式》GOF
      我们前面提及的流程就是子对象的一定算法,这个子对象的具体算法是经常变化的,但是复杂对象包含这个子对象是确定的,也就是说建造复杂对象的过程中,必须 包含子对象这个过程。但是这个部分“经常面临剧烈的变化”。显然,对于打开文件和打开设备,内部具体实现肯定是剧烈变化的。
      子对象内部是剧烈变化的,但是复杂对象的构建流程是确定的,也就是所谓的“组合到一起算法相对稳定”
      所谓“复杂对象的构建与其表示分离”,构建就是抽象出确定的流程,表示指的每个流程的具体实现。

Picture
下面通过具体实例说明如何使用建造者模式。
问题:通过建造者模式解决零件生产问题。

一、分析流程,创建抽象类
      我们综合零件的生产过程,可以抽象出如下过程。

1、零件设计 2、零件工艺 3、材料准备 4、加工 5、检查 6、入库

      工厂生产的零件有多种,各不相同,但是总的流程是确定的,因此需要创建一个Builder抽象类,这个类描述了所有零件的生产过程,但是对于任何实际的零件,从设计到工艺,从加工到检查,具体细节各不相同。

Picture
      零件抽象类作为所有具体零件的基类,因为LV无法实现真正的抽象类,所以把零件类放在库中,并设置零件类的库属性为私有,这样在库外部无法直接访问,间接实现了抽象的效果。
      零件抽象类的私有数据成员数据类型为字符串,用来描述零件的整个生产过程。
      零件的整个生产过程用5个方法来描述,这些方法都是可重写的,具体零件真正的生产过程延迟到子类中实现。

Picture
      上图为零件设计方法的程序框图,其它方法类似,目的是把当前过程写入到私有数据成员中,表示正在进行的过程。
      接下来创建零件类的属性,用来读取存储在字符串中的运行过程。

Picture
二、创建具体零件类

      零件抽象类设计完成后,具体零件的实现类就很容易了,只需要继承零件抽象类,并重写其中几个方法就可以了。

Picture
      我们创建了两个具体的零件,分别是齿轮和连杆,其基本流程是相同的,但是每个零件各个具体流程的实现方法是不同的,我们只是不同的字符串表示其不同的加工过程。

三、创建指挥者

      我们在零件抽象类中,创建了零件加工过程的各个过程,但是并没有真正体现出整个零件的加工次序,比如是先设计还是先加工等等。所以需要创建一个指挥者类, 该类私有数据成员中包括一个零件抽象类的实例,并负责具体建造的过程,指挥者保证了无论是齿轮还是连杆,都必须遵循同样的流程。

Picture
      上图中,最上面部分为指挥者类的私有数据成员,存储的是零件抽象类的实例。下面部分是指挥类的属性,负责写入具体类的实例,替换存储的私有数据。
      指挥者类中创建了一个方法,用来指挥具体零件的生产过程,对于任何具体零件,其生产过程都是一致的,这是抽象类中定义的可重写方法,指挥者不过是规定生产流程的次序。

Picture
      上面的方法确定了零件的生产过程为零件设计、零件工艺制作、零件加工、零件检查、零件入库,最后返回一个字符串,描述整个生产过程。

四、具体调用

创建了上述几个类后,具体调用就非常简单了。

Picture
      上面的程序框图分别创建了齿轮和连杆两个具体实例,在字符串中输出了他们整个生产过程。

Picture
Picture