定义:
将一个复杂产品对象的构建过程与它的表示分离开,从而使同样的创建过程可以创建出不同表示的产品对象。
建造者模式又叫做生成器模式,定义可以通俗的理解为:封装一个产品的构建过程,并允许按步骤构造。
设计类图:
建造者模式中的角色:
- Builder抽象的建造者,一般是一个接口类,提供构造产品步骤过程的一些方法接口。
- ConcreteBuilder具体的建造者,实现Buidler的接口方法,实现具体的构造过程,并最终返回一个产品对象。
- Product产品类,可以有多个不同的产品类,每个产品类应该对应一个Builder类,产品也可以是实现了模板方法模式的类。
在有的书中,建造者模式会多一个导演者(Director)角色,负责调用建造者来创建产品,那其实就是对Builder的调用,我这里直接归纳为Client为Builder的调用者,因为实际情况可能就是这样的,我们拿到Builder就可以去创建我们想要的产品了,至于需不需要在Builder外层再包装一层那就看你的需求了。
示例代码:
public interface Builder {
public void setPart1(String param);
public void setPart2(String param);
public void setPart3(String param);
public Product buildProduct();
}
public class ConcreteBuilder implements Builder {
private Product product = new Product();
@Override
public void setPart1(String param) {
product.setPart1(param);
}
@Override
public void setPart2(String param) {
product.setPart2(param);
}
@Override
public void setPart3(String param) {
product.setPart3(param);
}
@Override
public Product buildProduct() {
return product;
}
}
public class Product {
private String part1;
private String part2;
private String part3;
public Product() {
}
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
public String getPart3() {
return part3;
}
public void setPart3(String part3) {
this.part3 = part3;
}
}
public class Client {
public static void main(String[] args) {
//创建构造者
Builder builder = new ConcreteBuilder();
//构造者设置/构造产品的不同部分
builder.setPart1("param1");
builder.setPart2("param2");
builder.setPart3("param3");
//构造者返回一个产品对象
Product product = builder.buildProduct();
//使用产品对象
System.out.println(product.getPart1());
System.out.println(product.getPart2());
System.out.println(product.getPart3());
}
}
在上面的代码中,ConcreteBuilder的内部是首先创建好了一个Product对象,然后外部调用的时候会将各部分的参数设置给product对象,但是有时我们的Product构造函数是有必传参数的,就是必须传递参数才能构造产品对象,这时可以改造ConcreteBuilder如下:
public class ConcreteBuilder implements Builder {
private String part1;
private String part2;
private String part3;
@Override
public void setPart1(String param) {
this.part1 = param;
}
@Override
public void setPart2(String param) {
this.part2 = param;
}
@Override
public void setPart3(String param) {
this.part3 = param;
}
@Override
public Product buildProduct() {
return new Product(this.part1, this.part2, this.part3);
}
}
也就是说这种情况下是在buildProduct()被调用的时候才真正创建产品对象。
建造者模式在很多开源库中是很常见的模式,由于我是做Android开发的,在Android领域有很多开源库或者Android系统的api都是采用建造者模式,进一步,我们将Builder代码再稍微调整下:
public interface Builder {
public Builder setPart1(String param);
public Builder setPart2(String param);
public Builder setPart3(String param);
public Product buildProduct();
}
public class ConcreteBuilder implements Builder {
private String part1;
private String part2;
private String part3;
@Override
public ConcreteBuilder setPart1(String param) {
this.part1 = param;
return this;
}
@Override
public ConcreteBuilder setPart2(String param) {
this.part2 = param;
return this;
}
@Override
public ConcreteBuilder setPart3(String param) {
this.part3 = param;
return this;
}
@Override
public Product buildProduct() {
return new Product(this.part1, this.part2, this.part3);
}
}
public class Client {
public static void main(String[] args) {
//创建构造者
Builder builder = new ConcreteBuilder();
//构造者设置/构造产品的不同部分
Product product = builder.setPart1("param1")
.setPart2("param2")
.setPart3("param3")
.buildProduct();
//使用产品对象
System.out.println(product.getPart1());
System.out.println(product.getPart2());
System.out.println(product.getPart3());
}
}
如果你是做Android开发的同学,相信你已经看到了熟悉的代码,没错,就是链式调用的Builder模式,这种形式让书写更加方便,由于每次调用返回的是同一个对象,因此这样写也不违背迪米特法则。
建造者模式的优点
- 将一个复杂对象的创建过程封装起来。
- 允许对象通过多个步骤来创建,井且可以改变过程(这和只有一个步骤的工厂模式不同)。
- 向客户隐藏产品内部的表现。
- 产品的实现可以被替换,因为客户只看到一个抽象的接口。
建造者模式的用途和缺点
- 经常被用来创建组合结构。与工厂模式相比,采用建造者模式创建对象的客户,需要具备更多的领城知识。
- 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。
- 产品类柞常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。
参考: