建造者模式,是一种创建型模式。它将复杂对象的属性和构建行为分离开,使用抽象方式实现不同的构造过程,以此构造出不同表现(属性)的对象。
建造者模式是一步一步创建一个复杂的对象,它允许客户端只通过指定复杂对象的类型和内容,无需知道内部的具体构建细节,就可以构建对象。
建造者模式的四个角色
- 产品角色:一个具体的产品对象;
- 抽象建造者:定义构建对象过程的接口或抽象类;
- 具体建造者:实现抽象建造者,构建对象过程的具体实现;
- 指挥者:使用多态调用具体建造者,创建并给用户返回对象。主要作用:负责控制产品对象的构建过程;给客户端提供构建好的对象;
上面是建造者模式的UML类图。根据类图,我们再来思考上面的内容,
- 产品类只声明哪些组成部分;
- 将组成部分的具体内容是如何创建的行为,定义在另一个类中,这样就产生了具体创建者类;
- 但是,为了应付多种创建的行为,将具体建造者抽象出来,产生了抽象建造者,以便定义多种具体建造者;
- 然后思考,如何将产品类和建造者组装起来,以获得一个具体的产品对象?这就需要额外的类——指挥者类;指挥者类中调用建造者的方法,来创建产品对象;
- 客户端获取产品对象时,只需要定义哪种建造方式(具体建造者类)和指挥者类;
代码实现
通过上面的思考,相信大家应该对建造者模式有一定的了解,那接下来就使用代码来实现吧。代码案例中,使用建造者模式构建不同的house
对象。
/**
* 产品类:只需定义产品的组成部分。不关心组成部分怎么构建
*/
public class House {
private String basic;
private String walls;
private String roof;
//省略toString、get和set方法...
}
/**
* 抽象建造者:定义产品类的构建过程的接口
*/
public abstract class AbstractBuilder {
protected House house = new House();
public abstract void buildBasic();
public abstract void buildWalls();
public abstract void buildRoof();
public House getHouse(){
return house;
}
}
// 具体建造者:定义了产品某一类型的具体实现
//建造者1
public class HighHouse extends AbstractBuilder {
@Override
public void buildBasic() {
house.setBasic("高楼大厦地基");
}
@Override
public void buildWalls() {
house.setWalls("高楼大厦玻璃墙");
}
@Override
public void buildRoof() {
house.setRoof("高楼大厦房顶");
}
}
//建造者2
public class SimpleHouse extends AbstractBuilder {
@Override
public void buildBasic() {
house.setBasic("普通楼房地基");
}
@Override
public void buildWalls() {
house.setWalls("普通楼房砖墙");
}
@Override
public void buildRoof() {
house.setRoof("普通楼房房顶");
}
}
/**
* 指挥者:调用具体建造者构建对象
*/
public class Director {
private AbstractBuilder abstractBuilder;
public Director(AbstractBuilder abstractBuilder) {
this.abstractBuilder = abstractBuilder;
}
public House construct(){
abstractBuilder.buildBasic();
abstractBuilder.buildWalls();
abstractBuilder.buildRoof();
return abstractBuilder.getHouse();
}
}
/**
* 用户类:只关心获取怎样的对象,如何获取。
*/
public class Test {
public static void main(String[] args) {
//指定具体建造者
SimpleHouse simpleHouse = new SimpleHouse();
//通过指挥者直接获取需要的对象
Director director = new Director(simpleHouse);
House house = director.construct();
System.out.println(house);
}
}
总结
- 客户端不必知道产品对象构建的细节,将产品本身与产品构建过程解耦;
- 每个具体建造者各自独立,互不干涉;
- 添加新的具体建造者无需修改原有类库的代码,符合“开闭原则”;
- 如果产品之间差异性很大时,不适合使用建造模式;
与抽象工厂模式的区别
-
抽象工厂模式关心获取具体的对象,因为抽象工厂模式是实现对产品族的创建,用户需要指定从哪个工厂获取哪个对象,不关心对象是如何创建的。
-
而建造者模式中,产品类具有相同的组成部分,通过建造者类来构建具体内容。所以建造者模式中,产品类指定蓝图,建造者类完成具体的构建,指挥者类完成构建的流程。