设计模式(十六):建造者模式
一、概述
建造者模式很容易让人想到建房子,不管建刚需房、改善房还是别墅,它们都离不开地基、柱子、层面和墙体这些组成部分,建筑工人就是把这些组成部分一个个建起来,最后连成一体建出一栋栋楼房。
来看看建造者模式的定义,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建房子的过程都是相似的,但可以建出形形色色的房子。
二、结构类图
三、应用实例
我们用制造自行车为例子讲解建造者模式,自行车由车架、轮胎、脚踏等部件组成,如下图所示。自行车制造公司就是把这些零部件组装起来。
自行车制造公司的工程部门相当于指挥者,生产部门相当于建造者,当今共享单车做的比较大的摩拜和ofo相当于客户,单车就是产品了。结构图如下所示:
一起来看看如何用代码来实现
1、定义创建者接口,也就是生产线接口
package com.jet.pattern.builder; import com.jet.pattern.builder.impl.Bike; /** * description: * 自行车生产线接口 * Created by chenzanjin on 2017/2/22. */ public interface BikeBuilder { // 组装轮胎 public void buildTyres(); // 组装车架 public void buildFrame(); // 组装GPS定位装置 public void buildGPS(); // 获取自行车 public Bike getBike(); }
2、定义摩拜单车生产线
package com.jet.pattern.builder.impl; import com.jet.pattern.builder.BikeBuilder; /** * description: * 摩拜单车生产线 * Created by chenzanjin on 2017/2/22. */ public class MoBikeBuilder implements BikeBuilder { // 拥有单车对象 Bike bike = new Bike(); @Override public void buildTyres() { bike.setTyre("橙色轮胎"); } @Override public void buildFrame() { bike.setFrame("橙色车架"); } @Override public void buildGPS() { bike.setGps("mobike定制版GPS定位装置"); } @Override public Bike getBike() { return bike; } }
3、定义ofo单车生产线
package com.jet.pattern.builder.impl; import com.jet.pattern.builder.BikeBuilder; /** * description: * ofo单车生产线 * Created by chenzanjin on 2017/2/22. */ public class OfoBikeBuilder implements BikeBuilder { // 拥有单车对象 Bike bike = new Bike(); @Override public void buildTyres() { bike.setTyre("黑色轮胎"); } @Override public void buildFrame() { bike.setFrame("黄色车架"); } @Override public void buildGPS() { bike.setGps("ofo定制版GPS定位装置"); } @Override public Bike getBike() { return bike; } }
4、定义单车对象
package com.jet.pattern.builder.impl; /** * description: * 自行车对象 * Created by chenzanjin on 2017/2/22. */ public class Bike { // 轮胎 private String tyre; // 车架 private String frame; // GPS定位装置 private String gps; public String getTyre() { return tyre; } public void setTyre(String tyre) { this.tyre = tyre; } public String getFrame() { return frame; } public void setFrame(String frame) { this.frame = frame; } public String getGps() { return gps; } public void setGps(String gps) { this.gps = gps; } }
5、定义工程部
package com.jet.pattern.builder.impl; import com.jet.pattern.builder.BikeBuilder; /** * description: * 工程部门作为指挥者,可以指导生产部门作业 * Created by Administrator on 2017/2/22. */ public class EngineeringDepartment { // 用户告知指挥者想要什么样的单车 BikeBuilder bikeBuilder; public EngineeringDepartment(BikeBuilder bikeBuilder){ this.bikeBuilder = bikeBuilder; } // 指导组装单车 public void Construct(){ bikeBuilder.buildTyres(); bikeBuilder.buildFrame(); bikeBuilder.buildGPS(); } }
6、测试类
package com.jet.pattern.builder.impl; import com.jet.pattern.builder.BikeBuilder; /** * description: * 建造者测试类 * Created by Administrator on 2017/2/22. */ public class Test { public static void main(String[] args) { // 建造摩拜单车 BikeBuilder moBikeBuilder = new MoBikeBuilder(); EngineeringDepartment ed1 = new EngineeringDepartment(moBikeBuilder); ed1.Construct();// 指导组装 // 产出单车,体现建造和显示分离 Bike moBike = moBikeBuilder.getBike(); // 建造ofo单车 BikeBuilder ofoBikeBuilder = new MoBikeBuilder(); EngineeringDepartment ed2 = new EngineeringDepartment(ofoBikeBuilder); ed2.Construct();// 指导组装 Bike ofoBike = ofoBikeBuilder.getBike(); } }
四、优缺点
1、优点
(1)、产品的建造和表示分离,实现了解耦。
(2)、隐藏了产品的建造细节,用户只需关心产品的表示,而不需要了解是如何创建产品的。
(3)、体现了开闭原则,如上代码所示,如果需要再生产其他共享单车,只需要再开一条生产线即可,不影响其他生产线的作业。
2、缺点
(1)、当建造者过多时,会产生很多类,难以维护。
五、总结
建造者模式的使用场合是当创建复杂对象时,把创建对象成员和装配方法分离出来,放在建造者类中去实现,用户使用该复杂对象时,不用理会它的创建和装配过程,只关心它的表示形式。其实完全理解这个模式还是要一番思考的,难以搞懂的是指挥者似乎没什么存在的必要,在代码里也没体现它的作用,我们也可以把指挥者的方法放在建造者里面,但为什么没有这样做呢?我想这可能是考虑到单一责任原则,建造者只负责创建对象的各个部分,至于各个部分创建的顺序、装配方法它就不管了。还有就是当顺序要改变时,建造者可以不用改动,改动指挥者就好了,指挥者只有一个,建造者有很多,要改建造者就麻烦了。