首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

预览稿子: 初学Java设计模式随记 - 建造者(BUILDER)模式

2012-08-26 
预览文章: 初学Java设计模式随记 -- 建造者(BUILDER)模式?建造者(BUILDER)模式又叫生成器(BUILDER)模式。它

预览文章: 初学Java设计模式随记 -- 建造者(BUILDER)模式

?

建造者(BUILDER)模式又叫生成器(BUILDER)模式。它的定义如下:(参见GoF的设计模式与阎宏的《Java与模式》)

1. 用意:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

?

2. 参与者:

? 抽象建造者(Builder): 为创建一个产品(Prodcut)对象的各个部件指定抽象接口。
? 具体建造者(ConcretBuilder):

??? 实现抽象建造者(Builder)的接口以构造和装配该产品的各个部件。
??? 定义并明确它所创建的表示。
??? 提供一个检索产品的接口。

? 导演者(Director):构造一个使用抽象建造者(Builder)接口的对象。
? 产品(Prodcut):

??表示被构造的复杂对象。具体建造者(ConcretBuilder)创建该产品的内部表示并定义它的装配过程。
? 包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

?

3. 结构:


预览稿子: 初学Java设计模式随记 - 建造者(BUILDER)模式
?

根据GoF的设计模式,来描述一下建造者(BUILDER)模式使用时,各个角色之间的协作关系:

1. 客户创建导演者(Director)对象,并用它所想要的抽象建造者(Builder)的一个具体建造者(ConcretBuilder)对象进行配置。
2. 当产品的某个部件(PartOne, PartTwo, ...)需要被创建时,导演者(Director)就会通知具体建造者(ConcretBuilder)
3. 具体建造者(ConcretBuilder)处理导演者(Director)的请求,并将部件(PartOne, PartTwo, ...)添加到该产品(Prodcut)中。
4. 客户从具体建造者(ConcretBuilder)中检索产品(Prodcut)

?

===============小插曲===============================

在参看《设计模式可复用面向对象软件的基础》(GOF设计模式中文版)时,对于Builder模式中协作的第二条描述,无法理解:

一旦产品部件被生成,导向器就会通知生成器。(查看维基百科中文,也是这么翻译的)

对比英文原著,是这样描述的:

Director notifies the builder whenever a part of the product should be built.

?

那么,是不是应该翻译成下面的意思呢?

当产品的某个部件需要(应当)被创建的时候,导向器就会通知生成器。

(或者说,一旦产品部件需要被生成,导向器就会通知生成器。)

??

这里,可能有点较真了,不过,个人觉得,前后两种中文表达的应该是不同的含义。

=====================================================

?

?

根据现实的例子,来理解建造者模式。还是用生产汽车来举例。例子9

顾客想购买一辆一汽大众的汽车。

汽车实际就是一个产品族,即一套(一系列)汽车零部件产品(产品族)组合。

汽车的构造可是非常复杂的。它要有轮子,方向盘,座椅,发动机,颜色等等。

?

怎么这个例子看起来这么熟悉?

1. 好像与前一篇随记初学Java设计模式随记 -- 抽象工厂(Abstract Factory)模式很相似:

它们都可以创建复杂对象(产品集合或产品族)。

在GoF的设计模式中是这么说的:

Abstract Factory与Builder相似,因为它也可以创建复杂对象。主要的区别是Builder模式着重于一步步构造一个复杂对象。而Abstract Factory着重于多个系列的产品对象(简单的或是复杂的)。

?

也就是说,Builder模式关心的是怎样把复杂的产品的各个部件(或部件产品)给组装起来;

而Abstract Factory模式关心的是把哪些部件(或部件产品)给组装起来。

?

2. 好像与之前的另一篇随记初学Java设计模式随记 -- 工厂模式(Factory Pattern)也很相似:

回顾工厂模式的优势,与建造者模式的用意比较一下:

利用工厂模式可以将对象的创建过程和使用进行分离(也就是解藕)。

建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

个人觉得,

建造者模式更侧重于有规则或有序的创建(构建)过程;

工厂模式的创建(构建)过程比较随意。

??

?

其实,也可以从工厂建造者这两个名字来体会他们的差异:

建造者更像是工厂里的生产设备。?

工厂只关心生产什么产品,他只知道这个产品是由什么组成的;

建造者需要考虑怎么生产产品,他需要考虑产品的组成规则和方法。

?

或者说,在某种程度上,建造者模式就好像把工厂模式工厂角色的一些职责工作内容,给做了一些细化。?

导演者(Director)指导产品的生产,由建造者实施具体的生产。

?

继续这个例子,来体会建造者模式:

?

抽象建造者:?

?

/* * 建造者  */public interface CarBuilder {/** * 建造汽车的框架 */public void buildeCarSkeleton();/** * 给汽车装上发动机 */public void buildeCarEngine();/** * 给汽车装上轮子 */public void buildeCarWheels();/** * 给汽车装上导航设备 */public void buildeCarNavigation();/** * 安装车身(包含车门、车窗的安装,涂颜色) */public void buildeCarBody();}

?

具体建造者:(生产奥迪A6)

??

导演者:?

这里,由导演者指导建造者以一定的方式生产汽车(安装了导航系统)

?

/* * 导演者 */public class AudiDirector {CarBuilder builder;/** * 为导演者配置一个建造者 */public AudiDirector(CarBuilder builder){this.builder = builder;}/** * 按照一定的方式或规则建造汽车 */public void contruct(){builder.buildeCarSkeleton();builder.buildeCarEngine();builder.buildeCarNavigation();builder.buildeCarWheels();builder.buildeCarBody();}}

?

奥迪汽车(产品):?

?

/* * 产品 */public class AudiCar {private String carSkeleton;private Engine carEngine;private String carWheels;private String carNavigation = "";private String carDoor;private String carWindscreen;private String carColor;public AudiCar(){}/** * 汽车的颜色 */public void setCarColor(String carColor) {this.carColor = carColor;}/** * 汽车的车门 */public void setCarDoor(String carDoor) {this.carDoor = carDoor;}/** * 汽车发动机,发动机在这里是一个对象 */public void setCarEngine(Engine carEngine) {this.carEngine = carEngine;}/** * 汽车的框架 */public void setCarSkeleton(String carSkeleton) {this.carSkeleton = carSkeleton;}/** * 汽车轮子 */public void setCarWheels(String carWheels) {this.carWheels = carWheels;}/** * 汽车的挡风玻璃 */public void setCarWindscreen(String carWindscreen) {this.carWindscreen = carWindscreen;}/** * 汽车导航 */public void setNavigation(String navigation) {this.carNavigation = navigation;}/** * 一个汽车对象的描述 */public String toString(){return carSkeleton+ "," + carEngine.toString() +"," + carWheels + "," +carDoor + "," + carWindscreen + "," + carColor + "," + carNavigation;}}

?

汽车的一个部件对象:

?

/* * 一个部件对象(汽车发动机) */public class Engine {private String name;public Engine(String name){this.name = name;}public String toString(){return this.name;}}

?

客户端:

?

/* * 客户端 */public class Clients {public static void main(String[] args) {//创建一个建造者对象AudiCarBuilder builder = new AudiCarBuilder();//创建一个导演者,并为它配置一个建造者AudiDirector director1 = new AudiDirector(builder);//导演者将通知建造者去创建产品//在这个过程中,建造者将会根据导演者的请求,去创建组织并创建产品对象director1.contruct();//从具体建造者中检索产品(返回的是带导航的汽车产品)。AudiCar audiCar = builder.retrieveCar();System.out.println(audiCar);}}

?

运行结果:

汽车框架,奥迪A6发动机,车轮,车门,挡风玻璃,黑色,汽车导航

?

如果想生产一款没有导航系统的奥迪A6汽车,怎么实现呢?

只需要修改一下导演者就可以了。

新的导演者:(指示建造者不安装导航系统)

?

/* * 导演者 */public class AudiDirector {CarBuilder builder;/** * 为导演者配置一个建造者 */public AudiDirector(CarBuilder builder){this.builder = builder;}/** * 按照一定的方式或规则建造汽车 */public void contruct(){builder.buildeCarSkeleton();builder.buildeCarEngine();//不安装导航系统//builder.buildeCarNavigation();builder.buildeCarWheels();builder.buildeCarBody();}}

?

运行结果:(没有导航系统

?

??

汽车框架,奥迪A6发动机,车轮,车门,挡风玻璃,黑色,

?

?

?

?如果想生产奥迪A8且带导航系统的汽车,怎么实现呢?

(假设奥迪A6与奥迪A8的差别只是发动机)

只需要修改建造者类就可以了。

?

建造者:(只是改变自己的内部实现--奥迪A6发动机改为奥迪A8发动机)

?

/* * 具体建造者 */public class AudiCarBuilder implements CarBuilder {private AudiCar audiCar = new AudiCar();/** * 安装车身(包含车门、车窗的安装,涂颜色) */public void buildeCarBody() {audiCar.setCarDoor("车门");audiCar.setCarWindscreen("挡风玻璃");audiCar.setCarColor("黑色");}/** * 给汽车装上发动机 */public void buildeCarEngine() {Engine audiEngine = new Engine("奥迪A8发动机");audiCar.setCarEngine(audiEngine);}/** * 给汽车装上导航设备 */public void buildeCarNavigation() {audiCar.setNavigation("汽车导航");}/** * 建造汽车的框架 */public void buildeCarSkeleton() {audiCar.setCarSkeleton("汽车框架");}/** * 给汽车装上轮子 */public void buildeCarWheels() {audiCar.setCarWheels("车轮");}public AudiCar retrieveCar(){return audiCar;}}

?

?

运行结果:(更换成了奥迪A8发动机)

汽车框架,奥迪A8发动机,车轮,车门,挡风玻璃,黑色,汽车导航

??

?

从这个例子就可以看出,建造者模式的优势:

1. 导演者可以指定不同的生产方式(是否安装导航),而建造者不需要做任何改变,就可以得到不同的产品

2. 导演者不需要改变期望的生产方式,只需要建造者改变自己的内部实现(选择什么型号的发动机),也可以得到不同的产品。

??

关于建造者模式带来的效果,参看GoF的《设计模式》。

/* * 具体建造者 */public class AudiCarBuilder implements CarBuilder {private AudiCar audiCar = new AudiCar();/** * 安装车身(包含车门、车窗的安装,涂颜色) */public void buildeCarBody() {audiCar.setCarDoor("车门");audiCar.setCarWindscreen("挡风玻璃");audiCar.setCarColor("黑色");}/** * 给汽车装上发动机 */public void buildeCarEngine() {Engine audiEngine = new Engine("奥迪A6发动机");audiCar.setCarEngine(audiEngine);}/** * 给汽车装上导航设备 */public void buildeCarNavigation() {audiCar.setNavigation("汽车导航");}/** * 建造汽车的框架 */public void buildeCarSkeleton() {audiCar.setCarSkeleton("汽车框架");}/** * 给汽车装上轮子 */public void buildeCarWheels() {audiCar.setCarWheels("车轮");}public AudiCar retrieveCar(){return audiCar;}}

?

热点排行