设计模式(十六):建造者模式
一、概述
建造者模式很容易让人想到建房子,不管建刚需房、改善房还是别墅,它们都离不开地基、柱子、层面和墙体这些组成部分,建筑工人就是把这些组成部分一个个建起来,最后连成一体建出一栋栋楼房。
来看看建造者模式的定义,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建房子的过程都是相似的,但可以建出形形色色的房子。
二、结构类图
三、应用实例
我们用制造自行车为例子讲解建造者模式,自行车由车架、轮胎、脚踏等部件组成,如下图所示。自行车制造公司就是把这些零部件组装起来。
自行车制造公司的工程部门相当于指挥者,生产部门相当于建造者,当今共享单车做的比较大的摩拜和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)、当建造者过多时,会产生很多类,难以维护。
五、总结
建造者模式的使用场合是当创建复杂对象时,把创建对象成员和装配方法分离出来,放在建造者类中去实现,用户使用该复杂对象时,不用理会它的创建和装配过程,只关心它的表示形式。其实完全理解这个模式还是要一番思考的,难以搞懂的是指挥者似乎没什么存在的必要,在代码里也没体现它的作用,我们也可以把指挥者的方法放在建造者里面,但为什么没有这样做呢?我想这可能是考虑到单一责任原则,建造者只负责创建对象的各个部分,至于各个部分创建的顺序、装配方法它就不管了。还有就是当顺序要改变时,建造者可以不用改动,改动指挥者就好了,指挥者只有一个,建造者有很多,要改建造者就麻烦了。