概述
建造者模式构建复杂对象就像造汽车一样,一个一个组件一个一个步骤创建出来,它允许指定的组件对象和内容来创建,用户无需知道复杂对象如何创建,只需要明白通过这样方式可以得到复杂对象的实例。
定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的显示。
建造者角色
Builder
抽象建造者。它声明为创建一个Product对象的各个部件指定的抽象接口。
ConcreteBuilder
具体建造者。实现抽象接口,构建和装配各个部件。
Director
指挥者。构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。
1、隔离了客户与对象的生产过程。2、负责控制产品对象的生产过程。
Product
产品角色。
一个具体的产品对象。
类图
经典例子
Product 产品类
public class Product {
List<String> parts = new ArrayList<String>();
// 添加产品部件
public void add(String part) {
parts.add(part);
}
// 查询产品部件
public void show() {
for (String part: parts) {
System.out.println(part);
}
}
}
Builder 抽象建造者
public interface Builder {
void buildPartA();
void buildPartB();
Product getResult();
}
具体建造者A、B
public class ConcreteBuilderA implements Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.add("部件A");
}
@Override
public void buildPartB() {
product.add("部件B");
}
@Override
public Product getResult() {
return product;
}
}
public class ConcreteBuilderB implements Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.add("部件X");
}
@Override
public void buildPartB() {
product.add("部件Y");
}
@Override
public Product getResult() {
return product;
}
}
指挥者类
public class Director {
public void construct(Builder builder) {
builder.buildPartA();
builder.buildPartB();
}
}
测试类
public class Test {
public static void main(String[] args) {
Director director = new Director();
Builder builderA = new ConcreteBuilderA();
Builder builderB = new ConcreteBuilderB();
director.construct(builderA);
Product p1 = builderA.getResult();
p1.show();
director.construct(builderB);
Product p2 = builderB.getResult();
p2.show();
}
}
测试结果
部件A
部件B
部件X
部件Y
如果上面代码不是很好理解,接下里我们来写情景代码,通过情景代码更好的理解建造者模式。
情景代码
我们用制造自行车为例子讲解建造者模式,自行车由车架、轮胎、脚踏等部件组成,如下图所示。自行车制造公司就是把这些零部件组装起来 。
自行车制造公司的工程部门相当于指挥者,生产部门相当于建造者,当今共享单车做的比较大的摩拜和ofo相当于客户,单车就是产品了。
单车对象
public class Bike {
// 轮胎
private String tyre;
// 车架
private String frame;
// GPS定位装置
private String gps;
// 省略set()get()方法
}
创建者接口
public interface BikeBuilder {
// 组装轮胎
public void buildTyres();
// 组装车架
public void buildFrame();
// 组装GPS定位装置
public void buildGPS();
// 获取自行车
public Bike getBike();
}
摩拜单车生产线
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;
}
}
OFO单车生产线
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;
}
}
工程部
public class EngineeringDepartment {
// 用户告知指挥者想要什么样的单车
BikeBuilder bikeBuilder;
public EngineeringDepartment(BikeBuilder bikeBuilder){
this.bikeBuilder = bikeBuilder;
}
// 指导组装单车
public void Construct(){
bikeBuilder.buildTyres();
bikeBuilder.buildFrame();
bikeBuilder.buildGPS();
}
}
测试类
public static void main(String[] args) {
// 建造摩拜单车
BikeBuilder moBikeBuilder = new MoBikeBuilder();
EngineeringDepartment ed1 = new EngineeringDepartment(moBikeBuilder);
ed1.Construct();// 指导组装
// 产出单车,体现建造和显示分离
Bike moBike = moBikeBuilder.getBike();
System.out.println(moBike.getFrame()+" "+moBike.getTyre()+" "+moBike.getGps());
// 建造ofo单车
BikeBuilder ofoBikeBuilder = new OfoBikeBuilder();
EngineeringDepartment ed2 = new EngineeringDepartment(ofoBikeBuilder);
ed2.Construct();// 指导组装
Bike ofoBike = ofoBikeBuilder.getBike();
System.out.println(ofoBike.getFrame()+" "+ofoBike.getTyre()+" "+ofoBike.getGps());
}
测试结果
橙色车架 橙色轮胎 mobike定制版GPS定位装置
黄色车架 黑色轮胎 ofo定制版GPS定位装置
建造者模式的优缺点
优点
(1)产品的建造和表示分离,实现了解耦。
(2)隐藏了产品的建造细节,用户只需关心产品的表示,而不需要了解是如何创建产品的。
(3)体现了开闭原则,如上代码所示,如果需要再生产其他共享单车,只需要再开一条生产线即可,不影响其他生产线的作业。
缺点
(1)建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
(2)如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
使用场景
1、需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
2、隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
总结
建造者模式的使用场合是当创建复杂对象时,把创建对象成员和装配方法分离出来,放在建造者类中去实现,用户使用该复杂对象时,不用理会它的创建和装配过程,只关心它的表示形式。其实完全理解这个模式还是要一番思考的,难以搞懂的是指挥者似乎没什么存在的必要,在代码里也没体现它的作用,我们也可以把指挥者的方法放在建造者里面,但为什么没有这样做呢?我想这可能是考虑到单一责任原则,建造者只负责创建对象的各个部分,至于各个部分创建的顺序、装配方法它就不管了。还有就是当顺序要改变时,建造者可以不用改动,改动指挥者就好了,指挥者只有一个,建造者有很多,要改建造者就麻烦了。
源码地址: