概述
建造者模式(Builder Pattern):将一个复杂对象的构建与表示分离,使构建过程能可以创建出不同的表示。
- 对象创建的算法(步骤)固定,独立于对象的组成部分和装配方式。
- 对象有多部分组成,每一部分可以有不同的表述
比如网上组装一台电脑,电脑需要有显示屏、鼠标、键盘、主机、内存、CPU、显卡等部件构成,每一种显示屏、鼠标、键盘、主机、内存、CPU、显卡都有不同的品种,我们可以根据不同的需求和预算来让商人组装不同的电脑。
问题
如何提供一种稳定的封装机制将一个复杂对象的各个部分的变化隔离,从而保证系统中稳定的构建算法不随需求的变化而变化?
解决方案
将一个复杂对象的构建与表示分离,使构建过程能可以创建出不同的表示。
结构
- Builder(抽象构建者):它为创建一个产品Product对象的各个部件指定抽象接口。包含两类方法,第一类创建各个部件
builderPartX()
;第二类是创建出具体的产品build()
;Builder可以是接口也可以是抽象类。
电脑商人:1.知道电脑有哪些组件组成,并且买到这些组建 2.能根据这些买的组件组装一台具体的电脑 - ConcreteBuilder(具体构建者):它实现了Builder接口(抽象类),提供了具体的组件创建和组装的方法,明确定义了它提供的复杂对象Product,也可以提供一个方法返回创建好的复杂产品对象。
台式电脑商人:产品是台式电脑。 - Product(产品):一个复杂对象它由各个组件组成,具体建造者创建该产品的内部表示并定义它的装配过程。
台式电脑:由显示屏、鼠标、键盘、主机、内存、CPU、显卡等部件构成,有电脑商制造好卖给消费者。 - Director(指导者):它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。
消费者:要求电脑商人制造符合自己需求的电脑。
Java示例
场景:创造台式电脑
/**
* 抽象的电脑建造者
* @author jxiu
*
*/
public interface ComputerBuilder {
/**
* 创建屏幕
* @return
*/
void buildScreen(String screen);
/**
* 创建CPU
* @return
*/
void buildCPU(String cpu);
/**
* 创建显卡
* @return
*/
void buildGPU(String gpu);
/**
* 创建内存
* @return
*/
void buildMemory(String memory);
/**
* 创建硬盘
* @return
*/
void buildDisk(String disk);
/**
* 创造鼠标
* @param mouse
*/
void buildMouse(String mouse);
/**
* 创建电脑
* @return
*/
Computer build();
}
/**
* 具体的电脑建造者
* @author jxiu
*
*/
public class DeskopComputerBuilder implements ComputerBuilder{
Computer deskopComputer = new Computer();
@Override
public void buildScreen(String screen) {
deskopComputer.setScreen(screen);
}
@Override
public void buildCPU(String cpu) {
deskopComputer.setCPU(cpu);
}
@Override
public void buildGPU(String gpu) {
deskopComputer.setGPU(gpu);
}
@Override
public void buildMemory(String memory) {
deskopComputer.setMemory(memory);
}
@Override
public void buildDisk(String disk) {
deskopComputer.setDisk(disk);
}
@Override
public void buildMouse(String mouse) {
deskopComputer.setMouse(mouse);
}
@Override
public Computer build() {
return deskopComputer;
}
}
/**
* 电脑 产品对象
* @author jxiu
*
*/
public class Computer {
/** 屏幕*/
private String screen;
/** CPU*/
private String CPU;
/** GPU*/
private String GPU;
/** 内存*/
private String memory;
/** 硬盘*/
private String disk;
/** 鼠标*/
private String mouse;
public String getScreen() {
return screen;
}
public void setScreen(String screen) {
this.screen = screen;
}
public String getCPU() {
return CPU;
}
public void setCPU(String cPU) {
CPU = cPU;
}
public String getGPU() {
return GPU;
}
public void setGPU(String gPU) {
GPU = gPU;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getDisk() {
return disk;
}
public void setDisk(String disk) {
this.disk = disk;
}
public String getMouse() {
return mouse;
}
public void setMouse(String mouse) {
this.mouse = mouse;
}
@Override
public String toString() {
return "Computer [screen=" + screen + ", CPU=" + CPU + ", GPU=" + GPU + ", memory=" + memory + ", disk=" + disk
+ ", mouse=" + mouse + "]";
}
}
/***
* 消费者 指导者对象--指导者负责制定配件的类型
* @author jxiu
*
*/
public class Consumer {
private static ComputerBuilder builder = null;
/**
* 指导方法
* @return
*/
public static Computer buy () {
builder = new DeskopComputerBuilder();
builder.buildCPU("i7");
builder.buildGPU("1080TI");
builder.buildDisk("1T");
builder.buildMemory("DDR4");
// builder.buildMouse("普通鼠标");
builder.buildScreen("普通屏幕");
Computer computer = builder.build();
return computer;
}
public static void main(String[] args) {
System.out.println("用户购买电脑:" + buy());
}
}
effective java示例
effective java中提供了另外一种简化的建造者模式。
主要应用场景:类有多个可选参数。
解决方案:
- 提供多个重叠构造器(缺点:比较麻烦,容易出错)
- javaBeans模式(setter方法设置参数)(缺点:非线程安全,不能把类做成不可变模式)
- Builder模式
代码示例:
/**
* 抽象的建造者
* @author jxiu
*
* @param <T>
*/
public interface Builder<T> {
/**
* 建造方法
* @return
*/
public T build();
}
使用泛型可以创造出任何需要的对象。
/**
* 产品对象
* @author jxiu
*
*/
public class Computer {
/** 屏幕*/
private String screen;
/** CPU*/
private String CPU;
/** GPU*/
private String GPU;
/** 内存*/
private String memory;
/** 硬盘*/
private String disk;
/** 鼠标*/
private String mouse;
/**
* 私有的构造方法,使用具体builder对象建造
* @param builder
*/
private Computer(ComputerBilder builder) {
screen = builder.screen;
CPU = builder.CPU;
GPU = builder.GPU;
memory = builder.memory;
disk = builder.disk;
mouse = builder.mouse;
}
/**
* 具体的建造者
* @author jxiu
*
*/
public static class ComputerBilder implements Builder<Computer>{
/** 屏幕*/
private String screen;
/** CPU*/
private String CPU;
/** GPU*/
private String GPU;
/** 内存*/
private String memory;
/** 硬盘*/
private String disk;
/** 鼠标*/
private String mouse;
public ComputerBilder() {
}
public ComputerBilder screen(String screen) {
this.screen = screen;
return this;
}
public ComputerBilder CPU(String CPU) {
this.CPU = CPU;
return this;
}
public ComputerBilder GPU(String GPU) {
this.GPU = GPU;
return this;
}
public ComputerBilder memory(String memory) {
this.memory = memory;
return this;
}
public ComputerBilder disk(String disk) {
this.disk = disk;
return this;
}
public ComputerBilder mouse(String mouse) {
this.mouse = mouse;
return this;
}
@Override
public Computer build() {
return new Computer(this);
}
}
@Override
public String toString() {
return "Computer [screen=" + screen + ", CPU=" + CPU + ", GPU=" + GPU + ", memory=" + memory + ", disk=" + disk
+ ", mouse=" + mouse + "]";
}
}
/***
* 消费者 指导者对象--指导者负责制定配件的类型
* @author jxiu
*
*/
public class Consumer {
public static void main(String[] args) {
Computer computer = new ComputerBilder().screen("普通屏幕").CPU("i7").GPU("1080TI").disk("disk").memory("无线鼠标").build();
System.out.println("用户购买电脑:" + computer);
}
}
建造者模式和抽象工厂模式区别
- 建造者模式主要强调指导者(客户端使用者)可以根据需求指导产品的创建
- 抽象工厂模式是由工厂提供一系列的产品(工厂确定产品的类型和建造过程)。
缺点
- 如果产品之间的差异性很大,例如很多组成部分都不相同,不适合使用建造者模式,因此其使用范围受到一定的限制
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。