一个复杂的对象往往由多个子部件按一定的步骤组成。例如,汽车由发动机、轮胎、方向盘等部件组成的。
组成对象的各个部件可以灵活选择,而创建步骤大同小异。我们可以用建造者模式很好的描述该类产品的创建。
什么是建造者模式呢
“Separate the construction of a complex object from its representation so that the same construction process can create different representations.(将一个复杂对象的构建与它的表示分 离,使得同样的构建过程可以创建不同的表示。) ”
建造者模式中,将一个复杂的对象分解成多个简单的对象,产品的组成部分不变,但每个简单的对象内部是可以灵活多变的。
我们先不谈建造者模式的优缺点,现在来了解下建造者模式的的组成结构。
建造者模式主要由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成。这4个要素的说明如下:
- 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
- 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法
getResult()
。 - 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
- 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
这几种要素关系如下:
建造者模式
代码实现
产品类Product
@Data
public class Product {
private String partA;
private String partB;
private String partC;
public void show(){
String partA = getPartA();
String partB = getPartB();
String partC = getPartC();
System.out.println("这可能是东半球最好的产品...");
Console.log("组成结构:{},{},{}",partA,partB,partC);
}
}
Product
类包括3个部件字段,以及一个展示方法show()
。
建造者抽象类Builder
public abstract class Builder {
protected Product product = new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
public Product getResult() {
return product;
}
}
抽象类Builder
包括3个抽象方法,以及一个获取Product
对象的方法。
指挥者类Director
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product construct(){
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}
Director
类内部包含Director
构造函数用于传入Builder
对象,construct()
方法主要调用了建造类里面的方法,并返回Product
对象。
ConcreteBuilder
继承抽象建造者,实现里面的方法。
public class ConcreteBuilder extends Builder {
@Override
public void buildPartA() {
product.setPartA("建造 PartA");
}
@Override
public void buildPartB() {
product.setPartB("建造 PartB");
}
@Override
public void buildPartC() {
product.setPartC("建造 PartC");
}
}
调用类Client
public class Client {
public static void main(String[] args){
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
Product construct = director.construct();
construct.show();
}
}
测试结果:
代码语言:javascript复制这可能是东半球最好的产品...
组成结构:建造 PartA,建造 PartB,建造 PartC
有代码可知:
“首先创建了一个建造者,建造者里面有各种功能,为产品属性赋值 然后创建了一个指挥者,指挥者调用建造者功能从而能获得产品 ”
由建造模式我们可知,产品不直接创建,而是通过指挥者指挥建造者创建。这个是不是和工厂模式很像呢,但是需要注意,建造者模式比工厂模式要复杂。
当需要创建的产品具备复杂创建过程时,可以抽取出共性创建过程,然后交由具体实现类自定义创建流程,使得同样的创建行为可以生产出不同的产品,分离了创建与表示,使创建产品的灵活性大大增加。
关于建造者模式的思考
那么建造者模式有哪些优点呢?
同工厂模式一样,客户端不用知道产品内部的组成细节,就能获得产品;建造者与建造者之间是相互独立的。有利于系统扩展;并且修改某个建造者不会对其他模块产生影响。
那么什么时候使用建造者模式呢?《设计模式之禅》里写道:
“● 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。 ● 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可 以使用该模式。 ● 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建 造者模式非常合适。 ● 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程 中不易得到时,也可以采用建造者模式封装该对象的创建过程。该种场景只能是一个补偿方 法,因为一个对象不容易获得,而在设计阶段竟然没有发觉,而要通过创建者模式柔化创建 过程,本身已经违反设计的最初目标。 ”