建造者模式,光从名称来看,是否觉得和工厂模式是否觉得有点相近呢?工厂是要生产东西,建造者也是要生产东西,看上去真心的没啥太大区别。其实从个人感觉来说,建造者模式感觉比工厂模式更加灵活,对于属性较多的产品,使用建造者模式可能要好些。(欢迎来批)
《Java设计模式》中使用的例子是接着模版的方法来的,还是使用汽车的例子,汽车的动作有:启动(start),停止(stop),发动机轰鸣(engineBoom),喇叭叫(alarm)。运行(run),运行则是根据一定的顺序来排列之前提到的四个函数。根据需求分析,有多个品种的车子,每个品种的车的动作的顺序都不一样,现在的目标就是要合理地安排程序,来能够尽可能灵活地实现,多品种车子的创建。
首先,先定义车的模型(抽象模型),其中,sequence是表示动作执行的顺序,最重要的是run函数将要根据sequence来实现方法的执行,这样增大了灵活性,对于每个车子,只要通过函数设定好好sequence即可。

package com.cbf4life; import java.util.ArrayList; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 定义一个车辆模型的抽象类,所有的车辆模型都继承这里类 */ public abstract class CarModel { // 这个参数是各个基本方法执行的顺序 private ArrayList<String> sequence = new ArrayList<String>(); /* * 模型是启动开始跑了 */ protected abstract void start(); // 能发动,那还要能停下来,那才是真本事 protected abstract void stop(); // 喇叭会出声音,是滴滴叫,还是哔哔叫 protected abstract void alarm(); // 引擎会轰隆隆的响,不响那是假的 protected abstract void engineBoom(); // 那模型应该会跑吧,别管是人推的,还是电力驱动,总之要会跑 final public void run() { // 循环一遍,谁在前,就先执行谁 for (int i = 0; i < this.sequence.size(); i++) { String actionName = this.sequence.get(i); if (actionName.equalsIgnoreCase("start")) { // 如果是start关键字, this.start(); // 开启汽车 } else if (actionName.equalsIgnoreCase("stop")) { // 如果是stop关键字 this.stop(); // 停止汽车 } else if (actionName.equalsIgnoreCase("alarm")) { // 如果是alarm关键字 this.alarm(); // 喇叭开始叫了 } else if (actionName.equalsIgnoreCase("engine boom")) { // 如果是engine // boom关键字 this.engineBoom(); // 引擎开始轰鸣 } } } // 把传递过来的值传递到类内 final public void setSequence(ArrayList<String> sequence) { this.sequence = sequence; } }
然后是奔驰和宝马的模型,各做各的事:

package com.cbf4life; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 奔驰车模型 */ public class BenzModel extends CarModel { @Override protected void alarm() { System.out.println("奔驰车的喇叭声音是这个样子的..."); } @Override protected void engineBoom() { System.out.println("奔驰车的引擎是这个声音的..."); } @Override protected void start() { System.out.println("奔驰车跑起来是这个样子的..."); } @Override protected void stop() { System.out.println("奔驰车应该这样停车..."); } }

package com.cbf4life; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 宝马车模型 */ public class BMWModel extends CarModel { @Override protected void alarm() { System.out.println("宝马车的喇叭声音是这个样子的..."); } @Override protected void engineBoom() { System.out.println("宝马车的引擎是这个声音的..."); } @Override protected void start() { System.out.println("宝马车跑起来是这个样子的..."); } @Override protected void stop() { System.out.println("宝马车应该这样停车..."); } }
然后是建造者:carbuilder,它的工作就是根据需求生产汽车:

package com.cbf4life; import java.util.ArrayList; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 要什么顺序的车,你说,我给建造出来 */ public abstract class CarBuilder { // 建造一个模型,你要给我一个顺序要,就是组装顺序 public abstract void setSequence(ArrayList<String> sequence); // 设置完毕顺序后,就可以直接拿到这个车辆模型 public abstract CarModel getCarModel(); }
接下来是,奔驰和宝马的builder:

package com.cbf4life; import java.util.ArrayList; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 各种设施都给了,我们按照一定的顺序制造一个奔驰车 */ public class BenzBuilder extends CarBuilder { private BenzModel benz = new BenzModel(); @Override public CarModel getCarModel() { return this.benz; } @Override public void setSequence(ArrayList<String> sequence) { this.benz.setSequence(sequence); } }

package com.cbf4life; import java.util.ArrayList; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 第 88 页 您的设计模式 给定一个顺序,返回一个宝马车 */ public class BMWBuilder extends CarBuilder { private BMWModel bmw = new BMWModel(); @Override public CarModel getCarModel() { return this.bmw; } @Override public void setSequence(ArrayList<String> sequence) { this.bmw.setSequence(sequence); } }
builder只根据需求创造出一个汽车,提供了接收参数(sequence)和返回的生产实例的接口。虽然builder的功能类似工厂,但是他只是完成创造汽车的工作,如果一定要和工厂模式来比较的话,它的工作是工厂的一部分。最后一个类是Director类,Director整体才算是一个建造者:

package com.cbf4life; import java.util.ArrayList; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 导演安排顺序,生产车辆模型 */ public class Director { private ArrayList<String> sequence = new ArrayList(); private BenzBuilder benzBuilder = new BenzBuilder(); private BMWBuilder bmwBuilder = new BMWBuilder(); /* * A类型的奔驰车模型,先start,然后stop,其他什么引擎了,喇叭一概没有 */ public BenzModel getABenzModel() { // 清理场景,这里是一些初级程序员不注意的地方 this.sequence.clear(); // 这只ABenzModel的执行顺序 this.sequence.add("start"); this.sequence.add("stop"); // 按照顺序返回一个奔驰车 this.benzBuilder.setSequence(this.sequence); return (BenzModel) this.benzBuilder.getCarModel(); } /* * B型号的奔驰车模型,是先发动引擎,然后启动,然后停止,没有喇叭 */ public BenzModel getBBenzModel() { this.sequence.clear(); this.sequence.add("engine boom"); this.sequence.add("start"); this.sequence.add("stop"); this.benzBuilder.setSequence(this.sequence); return (BenzModel) this.benzBuilder.getCarModel(); } /* * C型号的宝马车是先按下喇叭(炫耀嘛),然后启动,然后停止 */ public BMWModel getCBMWModel() { this.sequence.clear(); this.sequence.add("alarm"); this.sequence.add("start"); this.sequence.add("stop"); this.bmwBuilder.setSequence(this.sequence); return (BMWModel) this.bmwBuilder.getCarModel(); } /* * D类型的宝马车只有一个功能,就是跑,启动起来就跑,永远不停止,牛叉 */ public BMWModel getDBMWModel() { this.sequence.clear(); this.sequence.add("start"); this.bmwBuilder.setSequence(this.sequence); return (BMWModel) this.benzBuilder.getCarModel(); } /* * 这里还可以有很多方法,你可以先停止,然后再启动,或者一直停着不动,静态的嘛 导演类嘛,按照什么顺序是导演说了算 */ }
注意,Director中定义了所有可能的出现的情况,然后调用相应的Builder来实现。最后是测试程序:

package com.cbf4life; /** * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you * all. 第 94 页 您的设计模式 这里是牛叉公司的天下,他要啥我们给啥 */ public class Client { public static void main(String[] args) { Director director = new Director(); // 1W辆A类型的奔驰车 for (int i = 0; i < 10; i++) { director.getABenzModel().run(); } // 100W辆B类型的奔驰车 for (int i = 0; i < 10; i++) { director.getBBenzModel().run(); } // 1000W量C类型的宝马车 for (int i = 0; i < 10; i++) { director.getCBMWModel().run(); } } }
整体感觉来看,制造者模式与工厂模式非常类似。对于这个例子,如果用工厂模式来思考的话:需要定义两个工厂BMWFactory和BenzFactory,这两个工厂分别生产宝马和奔驰,每个工厂中会有各种型号的车辆的生产方法。嗯嗯,应该是这样,不服来辩^_^