定义
定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
模式的角色和类图
角色
建造者(Builder)模式的主要角色如下。
- 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
- 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
- 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
- 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
- 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
类图
实现
具体代码如下:
/**
* @author hao
* 产品类
*/
public class Phone {
protected String cpu;
protected String camara;
protected String screen;
protected String battery;
@Override
public String toString() {
return "Phone{" +
"cpu='" + cpu + '\'' +
", camara='" + camara + '\'' +
", screen='" + screen + '\'' +
", battery='" + battery + '\'' +
'}';
}
}
/**
* 抽象建造者
*/
public interface PhoneBuilder {
Phone phone = new Phone();
void AssemblyCpu(String cpu);
void AssemblyCamara(String camara);
void AssemblyScreen(String screen);
void AssemblyBattery(String battery);
Phone build();
}
/**
* 具体建造者
*/
public class HwPhoneBuilder implements PhoneBuilder{
@Override
public void AssemblyCpu(String cpu) {
phone.cpu = cpu;
}
@Override
public void AssemblyCamara(String camara) {
phone.camara = camara;
}
@Override
public void AssemblyScreen(String screen) {
phone.screen = screen;
}
@Override
public void AssemblyBattery(String battery) {
phone.battery = battery;
}
@Override
public Phone build() {
return this.phone;
}
}
/**
* 指挥者类
*/
public class Direct {
private PhoneBuilder builder;
public Direct(PhoneBuilder builder) {
this.builder = builder;
}
public Phone getProduct(String cpu, String camara, String screen, String battery){
builder.AssemblyCpu(cpu);
builder.AssemblyCamara(camara);
builder.AssemblyScreen(screen);
builder.AssemblyBattery(battery);
return builder.build();
}
}
测试代码如下:
public class Maintest {
public static void main(String[] args){
Direct direct = new Direct(new HwPhoneBuilder());
Phone huaweiPhone = direct.getProduct("麒麟心", "5000万像素", "高清屏", "7000mA电池");
System.out.println(huaweiPhone);
}
}
结果:
Phone{cpu=‘麒麟心’, camara=‘5000万像素’, screen=‘高清屏’, battery=‘7000mA电池’}
这样看起来感觉很复杂。其实我们可以将指挥类和建造者类进行合并,并且实现链式调用。这样可以增强代码的可读性,以及方便我们使用建造者模式。我们去掉指挥类,改造下抽象建造者和具体建造者类,代码如下:
/**
* @author hao
* 抽象建造者
*/
public interface PhoneBuilder {
Phone phone = new Phone();
PhoneBuilder AssemblyCpu(String cpu);
PhoneBuilder AssemblyCamara(String camara);
PhoneBuilder AssemblyScreen(String screen);
PhoneBuilder AssemblyBattery(String battery);
Phone build();
}
/**
* @author hao
* 具体建造者
*/
public class HwPhoneBuilder implements PhoneBuilder{
@Override
public PhoneBuilder AssemblyCpu(String cpu) {
phone.cpu = cpu;
return this;
}
@Override
public PhoneBuilder AssemblyCamara(String camara) {
phone.camara = camara;
return this;
}
@Override
public PhoneBuilder AssemblyScreen(String screen) {
phone.screen = screen;
return this;
}
@Override
public PhoneBuilder AssemblyBattery(String battery) {
phone.battery = battery;
return this;
}
@Override
public Phone build() {
return this.phone;
}
}
我们再来测试下调用,测试类代码如下:
public class Maintest {
public static void main(String[] args){
HwPhoneBuilder builder = new HwPhoneBuilder();
Phone phone = builder.AssemblyCpu("麒麟心")
.AssemblyCamara("5000万像素")
.AssemblyScreen("高清屏")
.AssemblyBattery("7000mA电池")
.build();
System.out.println(phone);
}
}
结果:
Phone{cpu=‘麒麟心’, camara=‘5000万像素’, screen=‘高清屏’, battery=‘7000mA电池’}
我们实现了链式调用,也简化了代码。
但是仔细看测试类代码。我们发现和lombok中的@Builder标注的类创建对象的代码类似。没错!!
Lombok中的@Builder注解
lombok中的@Builder注解就是建造者模式的实现。
我们给Phone类标注@Builder
然后通过测试类代码进行测试,具体代码如下:
@Builder
public class Phone {
protected String cpu;
protected String camara;
protected String screen;
protected String battery;
@Override
public String toString() {
return "Phone{" +
"cpu='" + cpu + '\'' +
", camara='" + camara + '\'' +
", screen='" + screen + '\'' +
", battery='" + battery + '\'' +
'}';
}
}
只要一个产品类加上@Builder注解,就可以实现建造者模式。
我们通过代码测试下,测试类代码如下:
public class Maintest {
public static void main(String[] args){
Phone phone = Phone.builder()
.cpu("麒麟心")
.camara("5000万像素")
.screen("高清屏")
.battery("7000mA电池")
.build();
System.out.println(phone);
}
}
测试结果:
Phone{cpu=‘麒麟心’, camara=‘5000万像素’, screen=‘高清屏’, battery=‘7000mA电池’}
得到了同样的结果。@Builder注解首先通过Phone对象得到建造者对象PhoneBuilder然后对属性进行构造。然后调用PhoneBuilder的Build()方法返回构建好的Phone对象,大概就是这么个过程。所以后续我们可以直接利用@Builder注解来使用建造者模式。
至此创建型模式已经讲完````