应用背景
将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示。
实现
- 在bean中创建一个静态内部类Builder,然后将bean中的成员变量复制到Builder类中。
- 在bean中创建一个private 的构造函数(bean的构造函数),参数为刚刚在bean中创建的Builder类型。将Builder中的成员变量对应赋值给bean的成员变量。
- 在Builder中创建一个public的构造函数,参数是bean中的必填参数。
- 在Builder中创建set函数,对bean中那些可选参数进行赋值,返回值是Builder类型的实例
- 在Builder中创建一个build()方法,在其中构建Computer的实例并返回
- 下面来个简化版:
public class Students {
private String name;
//选填
private int age;
private int sex;
private int classNo;
//选填
private String addr;
private Students(Builder builder){
this.name = builder.name;
this.age = builder.age;
this.sex = builder.sex;
this.classNo = builder.classNo;
this.addr = builder.addr;
}
//--------------------------------------------------------------------//
public static class Builder{
private String name;
private int age;
private int sex;
private int classNo;
private String addr;
public Builder(String name,int sex,int classNo){
this.name = name;
this.sex = sex;
this.classNo = classNo;
}
public Builder setAge(int age){
this.age = age;
//注意这个地方返回的是当前的Builder,不在是单纯的age了
return this;
}
public Builder setAddr(String addr){
this.addr = addr;
return this;
}
public Students build(){
return new Students(this);
}
}
//------------------------------------------------------------//
}
使用:
Students students = new Students.Builder("zhangsan",1,2021)
.setAddr("北京")
.setAge(24)
.build();
图片处理框架Glide,网络请求框架Retrofit等都使用此模式。
这个构建者设计模式,具体实现就是利用了静态内部类。原来由我们直接new对象或者构造函数解决的,现在间接的通过静态内部内解决。最后链式创建的时候也是通过创建静态内部类对象的方式实现,只不过通过调用build()返回了我们需要的这个对象而已。上面这种实现方式,将该对象的创建分成了两部分,一部分是必填通过构造函数实现,另一部分是非必填,通过set方式实现。
- 创建者经典模式的实现
上图表示的意思,以电脑为例:- Product #最终的成品、对象
- 抽象的Builder #负责将内存、cpu、硬盘的装配
- Builder的具体实现ConcreteBuilder #这个就是对电脑各组件的描述
- Director #就是最终组装电脑的地方
表现到代码上为:
/**
* 这个bean就是告诉外界,电脑的组成有哪些。
*/
public class Computer {
private String cpu;
private String memory;
private String brand;
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
}
Builder
/**
* 抽象电脑组装过程的Builder类,这个Builder就是将一个电脑要分成这几个部分去组装
*/
public interface ComputerConfigBuilder {
void setCpu();
void setMemory();
void setBrand();
Computer getComputer();
}
/**
* 定义了电脑1的配置
*/
public class ComputerBuilder1 implements ComputerConfigBuilder {
private Computer computer;
@Override
public void setCpu() {
computer.setCpu("i7");
}
@Override
public void setMemory() {
computer.setMemory("16G");
}
@Override
public void setBrand() {
computer.setBrand("拯救者PXX");
}
@Override
public Computer getComputer() {
return computer;
}
}
/**
* 电脑2的配置
*/
public class ComputerBuilder2 implements ComputerConfigBuilder {
private Computer computer;
@Override
public void setCpu() {
computer.setCpu("i7");
}
@Override
public void setMemory() {
computer.setMemory("8G");
}
@Override
public void setBrand() {
computer.setBrand("拯救者RXX");
}
@Override
public Computer getComputer() {
return computer;
}
}
/**
* 这里按照电脑1和电脑2的配置进行组装
*/
public class Director {
private ComputerConfigBuilder configBuilder;
//告诉要组装哪一种
public void setBuilder(ComputerConfigBuilder builder){
this.configBuilder = builder;
}
//开始动手
public void createComputer(){
configBuilder.setCpu();
configBuilder.setBrand();
configBuilder.setMemory();
}
public Computer getComputer(){
return configBuilder.getComputer();
}
}
前面铺完路,来具体应用一下:
//创建组装者
Director director = new Director();
//告诉装机者,装那个配置的
director.setBuilder(new ComputerBuilder1());
//开始动手
director.createComputer();
//装机者返回装机的信息
Computer computer = director.getComputer();
写到这,真是可以体会到这种程序思想,对象复杂的时候用处比较大。让代码看着不会那么乱。但是简单的对象还是直接set比较快哈。虽然这个对象弄的比较简单。
不过,复杂的对象的话,最终对象的成员变量不一定是一个字段,如果是一个对象,这样的话建造者模式的优势是不是体现的更明显。例如上面cpu不是一个字段,而是一个cpu对象,里面包含了几核、功率等信息。