建造者模式(Builder)
- 定义 : 将一个复杂对象的构建与它的表示分离, 是的同样的构建过程可以创建不同的表示
- 用户只需指定需要建造的类型就可以得到它们, 建造过程及细节不需要知道
- 类型 : 创建型设计模式
适用场景
- 一个对象有非常复杂的内部结构
- 想把复杂对象的创建和使用分离
优点
- 封装性好, 创建和使用分离
- 扩展性好, 建造类之间独立, 一定程度上解耦
缺点
- 产生多余的Builder对象
- 产品内部发生变化, 建造者都要修改, 成本较大
模式角色
-
Builder : 为创建一个Product对象的各个部件指定抽象接口
-
ConcreteBuilder : Builder的实现类
- 实现Builder的接口以构造和装配该产品的各个部件
- 定义并明确它所创建的表示
- 提供一个检索产品的接口
-
Director : 构造一个使用Builder接口的对象
-
Product : 被构造的对象
- 表示被构造的复杂对象。ConcreteBuilder 创建该产品的内部表示并定义它的装配过程
- 包含定义组成部件的类,包括将这些部件装配成最终产品的接口
代码演示
场景: 组装一台电脑, 场景中各个类对应的角色如下 :
- Person,组装电脑的人, 对应Director
- ComputerBuilder, 对应ConcreteBuilder
- IComputerBuilder接口, 对应模式中的Builder
- Computer, 对应Product
版本一
UML类图
IComputerBuilder构造者接口, 对应模式中Builder
/**
* Builder接口
* 可以使用接口或者抽象类
* @author 七夜雪
* @create 2018-11-22 16:53
*/
public interface IComputerBuilder {
public void buildCpu(String cpu);
public void buildMemory(String memory);
public void buildMainboard(String mainboard);
public void buildDisk(String disk);
public Computer build();
}
ComputerBuilder构造者实现, 对应模式中ConcreteBuilder角色
/**
* builder模式中的builder
* @author 七夜雪
* 2018/11/14 13:51
*/
public class ComputerBuilder implements IComputerBuilder{
private Computer computer = new Computer();
@Override
public Computer build() {
return this.computer;
}
@Override
public void buildCpu(String cpu){
computer.setCpu(cpu);
}
@Override
public void buildMemory(String memory){
computer.setMemory(memory);
}
@Override
public void buildMainboard(String mainboard){
computer.setMainboard(mainboard);
}
@Override
public void buildDisk(String disk){
computer.setDisk(disk);
}
}
Computer电脑类, 对应模式中Product角色
/**
* 电脑类,Builder模式中的Product
*
* @author 七夜雪
* 2018/11/14 13:48
*/
public class Computer {
private String cpu;
private String memory;
private String mainboard;
private String disk;
public void setCpu(String cpu) {
this.cpu = cpu;
}
public void setMemory(String memory) {
this.memory = memory;
}
public void setMainboard(String mainboard) {
this.mainboard = mainboard;
}
public void setDisk(String disk) {
this.disk = disk;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", memory='" + memory + '\'' +
", mainboard='" + mainboard + '\'' +
", disk='" + disk + '\'' +
'}';
}
}
Person类, 对应模式中的Director角色
/**
* builder模式中的Director
* @author 七夜雪
* 2018/11/14 15:23
*/
public class Person {
private ComputerBuilder builder;
public Person(ComputerBuilder builder) {
this.builder = builder;
}
public Computer excuteBuilder(String cpu, String memory, String disk, String mainboard){
builder.buildCpu(cpu);
builder.buildMemory(memory);
builder.buildDisk(disk);
builder.buildMainboard(mainboard);
return builder.build();
}
}
测试类, 对应模式中的Client角色
/**
* builder模式测试类
* @author 七夜雪
* 2018/11/14 13:56
*/
public class Client {
public static void main(String[] args) {
ComputerBuilder builder = new ComputerBuilder();
Person director = new Person(builder);
Computer computer = director.excuteBuilder("酷睿I7", "金士顿 DDR4 16G", "三星512G SSD", "华硕X99");
System.out.println(computer);
}
}
版本二
版本一种, 如果product存在很多属性, 在执行director的excuteBuilder方法时要传入很多参数, 容易出现错误, 而且如果有些属性不需要的话, 也必须要传一个默认值, 所以更通用的一种写法, 就是讲Product和Builder写在一起, Builder作为Product类的内部类, 同时采用链式编程方式, 可以选择构造部分属性, 对于不需要的属性则不需要进行构造
UML 类图
代码如下:
/**
* 电脑类,Builder模式中的Product
*
* @author 七夜雪
* 2018/11/14 13:48
*/
public class Computer {
public Computer(ComputerBuilder computerBuilder) {
this.cpu = computerBuilder.cpu;
this.memory = computerBuilder.memory;
this.mainboard = computerBuilder.mainboard;
this.disk = computerBuilder.disk;
}
private String cpu;
private String memory;
private String mainboard;
private String disk;
public void setCpu(String cpu) {
this.cpu = cpu;
}
public void setMemory(String memory) {
this.memory = memory;
}
public void setMainboard(String mainboard) {
this.mainboard = mainboard;
}
public void setDisk(String disk) {
this.disk = disk;
}
public static class ComputerBuilder {
private String cpu;
private String memory;
private String mainboard;
private String disk;
public ComputerBuilder buildCPU(String cpu) {
this.cpu = cpu;
return this;
}
public ComputerBuilder buildMemory(String memory){
this.memory = memory;
return this;
}
public ComputerBuilder buildMainboard(String mainboard){
this.mainboard = mainboard;
return this;
}
public ComputerBuilder buildDisk(String disk){
this.disk = disk;
return this;
}
public Computer build(){
return new Computer(this);
}
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", memory='" + memory + '\'' +
", mainboard='" + mainboard + '\'' +
", disk='" + disk + '\'' +
'}';
}
}
/**
* Builder第二版测试类
*
* @author 七夜雪
* @create 2018-11-22 17:17
*/
public class ClientV2 {
public static void main(String[] args) {
Computer.ComputerBuilder builder = new Computer.ComputerBuilder();
Computer computer = builder.buildCPU("酷睿I9-9900K")
.buildMemory("海盗船 DDR4 64G")
.buildMainboard("华硕Z390")
.buildDisk("金士顿 1T SSD").build();
System.out.println(computer);
}
}
本文参考:
慕课网<java设计模式精讲 Debug 方式+内存分析>课程
四人帮<设计模式>