将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
建造模式是将复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入建造者和建造工具,对于内部是如何建造成成品的,调用者无需关心,其类图如下。
建造者角色
Product : 产品类,由多个部件构成。
class Product {
List<String> parts = new ArrayList<String>();
public void AddPart(String part) {
parts.add(part);
}
public void show() {
for (String part : parts) {
System.out.println(part);
}
}
}
Builder : 抽象建造者,确定产品由 AB 部件构成,并声明一个得到产品建造后结果的方法 getResult。
interface Builder {
public void buildPartA();
public void buildPartB();
public Product getResult();
}
ConcreteBuilder : 实现 Builder 接口中的具体方法。
class ConcreteBuilder implements Builder {
private Product product = new Product();
public void buildPartA() {
product.AddPart("part A");
}
public void buildPartB() {
product.AddPart("part B");
}
public Product getResult() {
return product;
}
}
Director : 指挥者类,指挥建造 Product 的过程(控制构建各部分组件的顺序)。
class Director {
public void construct(Builder builder) {
builder.buildPartA();
builder.buildPartB();
}
}
Client : 用户并不需要知道具体的建造过程,只需指定建造 Product 具体类型。
public class BuilderPattern {
public static void main(String[] args) {
Director director = new Director();
Builder builder = new ConcreteBuilder();
director.construct(builder);
Product product = builder.getResult();
product.show();
}
}
与抽象工厂的区别:在建造者模式里,有个指导者,由指导者来管理建造者,用户是与指导者联系的,指导者联系建造者最后得到产品。即建造模式可以强制实行一种分步骤进行的建造过程。
JDK 中使用的建造者模式
DOMParser 使用 parse 方法建造 Document 对象,使用 getDocument 获取 XML 的 Document 对象。
建造者模式的优点
1、建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。
2、建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。
建造者模式与工厂模式的区别
1、建造者模式与工厂模式是极为相似的,总体上,建造者模式仅仅只比工厂模式多了一个“导演类”的角色。在建造者模式的类图中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。
2、与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。
总结
建造者模式与工厂模式类似,适用的场景也很相似。一般来说,如果产品的建造很复杂,那么请用工厂模式;如果产品的建造更复杂,那么请用建造者模式。