首先贴出一篇不错的关于builder模式的博文:点击打开链接 文中举的第一个反例的博文在这里:点击打开链接
修改后的UML图如下:
说实在的,这个模式我理解不是很深入,因为在实践中没用过,看网上的介绍也是不知所以然,还是那句话,理论和实践还是有差距的。下面有些话我都不知道说的是什么鬼!
有几点:
1. 首先一点要搞注意,这里的builder不是你要创建的对象,它是你要创建对象(Equipment)的一个工具!builder基类是可以没有派生类而单独存在的!在产品对象变化比较大的时候,才需要继承出一个派生类!
2. 这里的CreateEQP要不要带EQPBuilder参数,每次调用都传入builder父类,还是作为LCDFactory的构造参数传入,就像图中client代码那样!这是两种逻辑,可能都可行吧!
3. SuperEQPBuilder子类应该带有GetEQP()函数,这个函数中可能也是先buildxxx(),然后retunr newSuperEQP,提供给Director一个复杂产品对象的装配逻辑。也可能这些装配逻辑会在CreateEQP函数中,如图中那样!
4.LCDFactory 并不需要指导具体生成器生成的产品,它只需要了解如何使用生成器制造产品,要制造的产品的细节,只有具体生成器才知道。
5. 在CreateEQP函数中装配对象算法的方式自行决定!
6. Product:由ConcreteBuilder创建这个复杂产品的内部表示并定义它的装配过程。通常,Product定义了它的组成部件的类,以及将这些部件装配成最终产品的接口。一个系统中可能还有多个Product类,而且这些类之间不一定会有共同的接口,可以是完全互不相关的。生成器模式创建的产品不一定有共同的父类,只要有类似的构造过程即可。
生成器模式用于分步构建一个复杂的对象,如何划分步骤是基本稳定的,而复杂对象的各个部分的创建过程则经常变化,这就需要用builder来对创建过程进行封装。定义一个新的生成器,就可以改变产品的内部表示。生成器模式中的指导者角色控制着生成器生成部件的过程。
整个图反映了作者的思想,重点就在Director中的CreateEQP中,也就是说把由Builder继承来生成子类的方法,改在CreateEQP中进行。我个人特别不理解的是:builder子类相当于一个创建某类东西的模板,按作者的意思,不能因为某个特点不同就继承出一个Concretbuilder子类,那么是不是只继承出一些常用的呢?其它不常用的构造方法放在Director的CreateEQP中?原文中有这样句话:只要我们将不同的ConcreteBuilder传递给同一Director,就可以得到不同的东西,从而复用了创建东西的算法,达到同样的构件过程可以创建不同的表示。当且仅当新的部件(SuperXXOO)需要加入到系统时,才需要去创建新的ConcreteBuilder;如果要创建SuperEquipment,我们只需要将SuperEQPBuilder的示例传递给LCDFactory就足够了. 看来这里的CreateEQP函数要好好设计一下才行! 具体的对象创建(new)都是在builder或子类的getResult()函数里进行的!
ConcreteBuilder只是提供了使用部件装配产品的操作接口,但不提供具体的装配算法,装配算法在导向器[Director]中定义。也就是说,在CreateEQP函数里,通过传进来的ConcreteBuilder参数,来调用它对应的buildPart接口,调用哪些由Director决定,而不是一成不变的就只能生产某一种特定Concret产品!这就容易让人明白了,ConcreteBuilder只是提供了某一特定产品的组装接口,组装算法还在Director里。
单纯的Builder模式中,“不同Product类型”的组成部件之间,不能进行组合或替换!由上面的分析,这个很好理解,不能把变形金刚的头放在正常人身上!
下面是另一个例子的UML图