1、定义
将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。建造者模式是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
2、模式结构
构造者模式由四部分组成:
- Builder(抽象构造者):给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者角色。具体建造者类必须实现这个接口所要求的两个方法:一种是建造方法,另一种是返回结构方法。一般来说,产品所包含的零件数目与建造方法的数目相符。换言之,有多少零件,就有多个相应的建造方法。
- ConcreteBuilder(具体构造者):与应用程序紧密相关的一些类,它们在应用程序调用下创建产品的实例。这个角色要完成的任务包括:实现抽象创造者所声明的接口,给出一步一步地完成创建产品实例的操作;在建造过程完成后,提供产品的实例。
- Director(导演者):负责调用具体建造者按照顺序建造产品。导演者只负责调度,真正执行的是具体建造者角色。
- Product(产品):产品便是建造中的复杂对象。
3、实例
3.1 房子(Product)
public class House {
private String basis;
private String wall;
private String roof;
// toString、getter方法和setter方法
}
3.2 抽象构造者类(Builder)
public abstract class HouseBuilder {
public abstract void buildBasis();
public abstract void buildWall();
public abstract void buildRoof();
public abstract House getHouse();
}
3.3 具体构造者类(ConcreteBuilder)
public class HighBuilding extends HouseBuilder{
private House house = new House();
@Override
public void buildBasic() {
house.setBasic("高楼打地基100m深");
}
@Override
public void buildWall() {
house.setWall("高楼砌墙30cm宽");
}
@Override
public void buildRoof() {
house.setRoof("高楼使用透明屋顶");
}
@Override
public House getHouse(){
return house;
}
}
3.4 导演者类(Director)
public class HouseDirector {
public void buildHouse(HouseBuilder houseBuilder) {
houseBuilder.buildBasis();
houseBuilder.buildWall();
houseBuilder.buildRoof();
}
}
3.5 客户端调用
public class Client {
public static void main(String[] args) {
HouseBuilder highBuilding = new HighBuilding();
HouseDirector houseDirector = new HouseDirector();
houseDirector.buildHouse(highBuilding);
System.out.println(highBuilding.getHouse().toString());
}
}
4、适用场景
- 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
- 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
- 对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在指挥着类,而不在建造类中。
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
5、在JDK的应用
StringBuilder的部分源码:
- Appendable接口定义了多个append方法(抽象方法),即Appendable为抽象建造者。
- AbstractStringBuilder实现了Appendable接口方法,这里的AbstractStringBuilder已经是建造者,只是不能实例化。
- StringBuilder即充当了指挥者角色,同时充当了具体的建造者,建造方法的实现是由AbstractStringBuilder完成,而StringBuilder继承了AbstractStringBuilder.
6、优缺点
6.1 优点
- 客户端(应用程序)不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
- 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
- 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
*增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
6.2 缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很大具体建造者类来实现这种变化,导致系统变得很庞大,因此在这种情况下,要考虑是否选择建造者模式。
7、建造者模式和抽象工厂的区别
- 建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
- 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象;而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
- 如果将抽象工厂模式看出汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,那么对部件的组装可以返回一辆完整的汽车。