定义:
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
使用场景:
单单看介绍,其实我们还是不明白建造者模式到底是干什么的,简单来说:当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。
实现:
例如我们现在有一个计算机类Computer,其中cpu与ram是必填参数,而其他3个是可选参数,那么我们如何构造这个类的实例呢,通常有两种常用的方式:
1. 折叠构造函数模式(telescoping constructor pattern )
public class Computer {
...
public Computer(String cpu, String ram) {
this(cpu, ram, 0);
}
public Computer(String cpu, String ram, int usbCount) {
this(cpu, ram, usbCount, "罗技键盘");
}
public Computer(String cpu, String ram, int usbCount, String keyboard) {
this(cpu, ram, usbCount, keyboard, "三星显示器");
}
public Computer(String cpu, String ram, int usbCount, String keyboard, String display) {
this.cpu = cpu;
this.ram = ram;
this.usbCount = usbCount;
this.keyboard = keyboard;
this.display = display;
}
}
2. Javabean 模式
public class Computer {
...
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getRam() {
return ram;
}
public void setRam(String ram) {
this.ram = ram;
}
public int getUsbCount() {
return usbCount;
}
...
}
者两种方式都可以解决问题,但是我们现在要说的是第三种方式,建造者模式。
3. 建造者模式
builder模式有4个角色:
- Product: 最终要生成的对象,例如 Computer实例。
- Builder: 构建者的抽象基类(有时会使用接口代替)。其定义了构建Product的抽象步骤,其实体类需要实现这些步骤。其会包含一个用来返回最终产品的方法Product getProduct()。
- ConcreteBuilder: Builder的实现类。
- Director: 决定如何构建最终产品的算法. 其会包含一个负责组装的方法void Construct(Builder builder), 在这个方法中通过调用builder的方法,就可以设置builder,等设置完成后,就可以通过builder的 getProduct() 方法获得最终的产品。
1. 创建builder对象:
package com.example.pattern.designpattern.builder;
import lombok.Data;
/**
* Product
* cpu 和 ram 必填,其它选填
*
* @author liuyuan
* @version Computer.java, v 0.1 2020-05-05 16:12
*/
@Data
public class Computer {
private String cpu;
private String ram;
private int usbCount;
private String keyboard;
private String display;
public Computer(String cpu, String ram) {
this.cpu = cpu;
this.ram = ram;
}
}
2. 构建者的抽象基类:
package com.example.pattern.designpattern.builder;
/**
* 抽象构建者类 Builder
*
* @author liuyuan
* @version AbstractComputerBuilder.java, v 0.1 2020-05-05 16:15
*/
public abstract class AbstractComputerBuilder {
public abstract void setUsbCount();
public abstract void setKeyboard();
public abstract void setDisplay();
public abstract Computer getComputer();
}
3. Builder的实现类:
/**
* ConcreteBuilder
*
* @author liuyuan
* @version LenovoComputerBuilder.java, v 0.1 2020-05-05 16:18
*/
public class LenovoComputerBuilder extends AbstractComputerBuilder {
private Computer computer;
public LenovoComputerBuilder(String cpu, String ram) {
computer = new Computer(cpu, ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(6);
}
@Override
public void setKeyboard() {
computer.setKeyboard("联想键盘~~");
}
@Override
public void setDisplay() {
computer.setDisplay("联想显示器~~");
}
@Override
public Computer getComputer() {
return computer;
}
}
/**
* ConcreteBuilder
*
* @author liuyuan
* @version MacComputerBuilder.java, v 0.1 2020-05-05 16:16
*/
public class MacComputerBuilder extends AbstractComputerBuilder {
private Computer computer;
public MacComputerBuilder(String cpu, String ram) {
computer = new Computer(cpu, ram);
}
@Override
public void setUsbCount() {
computer.setUsbCount(4);
}
@Override
public void setKeyboard() {
computer.setKeyboard("苹果键盘~~");
}
@Override
public void setDisplay() {
computer.setDisplay("苹果显示器~~");
}
@Override
public Computer getComputer() {
return computer;
}
}
4. Director,指导者类:
package com.example.pattern.designpattern.builder;
/**
* 指导者 Director
*
* @author liuyuan
* @version ComputerDirector.java, v 0.1 2020-05-05 16:18
*/
public class ComputerDirector {
public void makeComputer(AbstractComputerBuilder builder) {
builder.setUsbCount();
builder.setDisplay();
builder.setKeyboard();
}
}
- 测试:
/**
* @author liuyuan
* @version Test.java, v 0.1 2020-05-05 16:19
*/
public class Test {
public static void main(String[] args) {
ComputerDirector director = new ComputerDirector();
AbstractComputerBuilder builder = new MacComputerBuilder("I5处理器", "三星125");
director.makeComputer(builder);
Computer macComputer = builder.getComputer();
System.out.println("mac computer:" + macComputer.toString());
AbstractComputerBuilder lenovoBuilder = new LenovoComputerBuilder("I7处理器", "海力士222");
director.makeComputer(lenovoBuilder);
Computer lenovoComputer = lenovoBuilder.getComputer();
System.out.println("lenovo computer:" + lenovoComputer.toString());
}
}
到这里,经典的建造者模式基本说完了,相对还是比较复杂的,其实我们可以使用建造者模式的一种变种,Builder在Java中一种简化的使用方式:
4. 建造者拓展方式
package com.example.pattern.designpattern.builder;
import lombok.Data;
/**
* @author liuyuan
* @version ComputerBuild.java, v 0.1 2020-05-05 16:59
*/
@Data
public class ComputerBuild {
private String cpu;
private String ram;
private int usbCount;
private String keyboard;
private String display;
private ComputerBuild(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.usbCount = builder.usbCount;
this.keyboard = builder.keyboard;
this.display = builder.display;
}
public static class Builder {
private String cpu;
private String ram;
private int usbCount;
private String keyboard;
private String display;
public Builder(String cup, String ram) {
this.cpu = cup;
this.ram = ram;
}
public Builder setUsbCount(int usbCount) {
this.usbCount = usbCount;
return this;
}
public Builder setKeyboard(String keyboard) {
this.keyboard = keyboard;
return this;
}
public Builder setDisplay(String display) {
this.display = display;
return this;
}
public ComputerBuild build() {
return new ComputerBuild(this);
}
}
}
直接通过链式调用,一步步把对象构建出来:
public static ComputerBuild test() {
return new ComputerBuild.Builder("因特尔", "三星")
.setDisplay("三星24寸")
.setKeyboard("罗技")
.setUsbCount(2)
.build();
}