设计模式之建造者(Builder)模式
示意图:
建造者模式是日常开发中比较常见的设计模式,它的主要作用就是将复杂事物创建的过程抽象出来,该抽象的不同实现方式不同,创建出的对象也不同。通俗的讲,创建一个对象一般都会有一个固定的步骤,这个固定的步骤我们把它抽象出来,每个抽象步骤都会有不同的实现方式,不同的实现方式创建出的对象也将不同。举个常见的例子,想必大家都买过电脑,电脑的生产或者组装其实就是属于建造者模式,我们知道,电脑的生产都需要安装CPU、内存条、硬盘等元器件。我们可以把这个安装步骤抽象出来,至于到底装哪种CPU,比如i5还是i7就是对该抽象安装步骤的具体实现。
经典Buider模式中有四个角色:
- 要建造的产品Product -- 组装的电脑
- 抽象的Builder -- 装CPU、内存条、硬盘等抽象的步骤
- Builder的具体实现ConcreteBuilder -- 对上述抽象步骤的实现,比如装i5CPU、8G内存条、1T硬盘
- 使用者Director -- 电脑装机人员
接下来我们来看下用代码如何实现上述组装电脑的过程:
1 目标产品:电脑
package design.builder;
public class Computer {
/*CPU*/
private String CPU;
/*内存*/
private String memory;
/*硬盘*/
private String hardDisk;
/*键盘*/
private String keyboard;
/*鼠标*/
private String mouse;
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 getHardDisk() {
return hardDisk;
}
public void setHardDisk(String hardDisk) {
this.hardDisk = hardDisk;
}
public String getKeyboard() {
return keyboard;
}
public void setKeyboard(String keyboard) {
this.keyboard = keyboard;
}
public String getMouse() {
return mouse;
}
public void setMouse(String mouse) {
this.mouse = mouse;
}
@Override
public String toString() {
return "Computer{" +
"CPU='" + CPU + '\'' +
", memory='" + memory + '\'' +
", hardDisk='" + hardDisk + '\'' +
", keyboard='" + keyboard + '\'' +
", mouse='" + mouse + '\'' +
'}';
}
}
可以看到这个Computer类中有五个基本属性CPU、内存条、硬盘、键盘和鼠标,然后还有一个toString方法,用于之后方便打印信息用。
2.接下来我们来创建一个抽象的电脑组装过程的Builder类:
package design.builder;
public interface Builder {
void setCPU();
void setMemery();
void setHardDisk();
void setKeyboard();
void setMouse();
Computer getComputer();
}
电脑组装一般都需要安装CPU、内存条、硬盘、键盘鼠标等,我们把这一安装过程给抽象出来,也就是这里的Builder ,至于具体安装什么需要其实现类来实现,另外其中还定义了一个获取Conputer的方法。
3.好了,有了抽象的组装过程,接下来我们就需要创建具体的实现类。我们知道电脑一般都有低配版和高配版,不同配置,组装成的电脑自然就不一样。接下我们首先来创建一个低配版的套餐LowConfigBuilder 和高配版本套餐,让其实现Builder:
package design.builder;
public class HighConfigBuider implements Builder {
private Computer mComputer;
public HighConfigBuider() {
this.mComputer = new Computer();
}
@Override
public void setCPU() {
mComputer.setCPU("i7");
}
@Override
public void setMemery() {
mComputer.setMemory("16G");
}
@Override
public void setHardDisk() {
mComputer.setHardDisk("1T");
}
@Override
public void setKeyboard() {
mComputer.setKeyboard("机械键盘");
}
@Override
public void setMouse() {
mComputer.setMouse("无线鼠标");
}
@Override
public Computer getComputer() {
return mComputer;
}
}
package design.builder;
public class LowConfigBuilder implements Builder {
private Computer mComputer;
public LowConfigBuilder() {
this.mComputer = new Computer();
}
@Override
public void setCPU() {
mComputer.setCPU("i5");
}
@Override
public void setMemery() {
mComputer.setMemory("8G");
}
@Override
public void setHardDisk() {
mComputer.setHardDisk("500G");
}
@Override
public void setKeyboard() {
mComputer.setKeyboard("薄膜键盘");
}
@Override
public void setMouse() {
mComputer.setMouse("有线鼠标");
}
@Override
public Computer getComputer() {
return mComputer;
}
}
4 上面我们已经定义好了两种配置方案,接下我们还需要一名装机人员Director:
package design.builder;
public class Director {
private Builder mBuilder;
public void setBuilder(Builder builder) {
this.mBuilder = builder;
}
public void createComputer() {
mBuilder.setCPU();
mBuilder.setMemery();
mBuilder.setHardDisk();
mBuilder.setKeyboard();
mBuilder.setMouse();
}
public Computer getComputer() {
return mBuilder.getComputer();
}
}
5.演示
接下来我们就来创建一台电脑试下
package design.builder;
/**
* 建造者模式是日常开发中比较常见的设计模式,它的主要作用就是将复杂事物创建的过程抽象出来,
* 该抽象的不同实现方式不同,创建出的对象也不同。通俗的讲,创建一个对象一般都会有一个固定的步骤,
* 这个固定的步骤我们把它抽象出来,每个抽象步骤都会有不同的实现方式,不同的实现方式创建出的对象也将不同。
* 举个常见的例子,想必大家都买过电脑,电脑的生产或者组装其实就是属于建造者模式,
* 我们知道,电脑的生产都需要安装CPU、内存条、硬盘等元器件。
* 我们可以把这个安装步骤抽象出来,至于到底装哪种CPU,比如i5还是i7就是对该抽象安装步骤的具体实现。
* <p>
* 经典Buider模式中有四个角色:
* <p>
* 要建造的产品Product -- 组装的电脑
* 抽象的Builder -- 装CPU、内存条、硬盘等抽象的步骤
* Builder的具体实现ConcreteBuilder -- 对上述抽象步骤的实现,比如装i5CPU、8G内存条、1T硬盘
* 使用者Director -- 电脑装机人员
*/
public class BuilderMain {
public static void main(String[] args) {
Director director = new Director();//创建装机人员
director.setBuilder(new LowConfigBuilder()); //告诉装机人员电脑配置,这里为低配版
director.createComputer(); //装机人员开始组装
Computer computer = director.getComputer(); //从装机人员获取组装好的电脑
System.out.print("电脑配置:" + computer.toString()); //查看电脑配置
director.setBuilder(new HighConfigBuider());
director.createComputer();
computer = director.getComputer();
System.out.print("电脑配置:" + computer.toString());
}
}
结果:
通过具体的对象来构造抽象类,通过一个Director来封装构建复杂产品对象的过程,对外隐藏构建细节,则利用Buider和Director一起构建复杂且不同的对象,在实际开发过程中则经常忽略Director这个类,取而代之的是
new TestBuilder().setA(“A”).setB(“B”).create()
GoF 在《设计模式》一书中给出的关于 Builder 模式的意图是非常容易理解、间接的:
将一个复杂对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示(在示例
代码中可以通过传入不同的参数实现这一点)。
Builder 模式和 AbstractFactory 模式在功能上很相似,因为都是用来创建大的复杂的对
象,它们的区别是: Builder 模式强调的是一步步创建对象,并通过相同的创建过程可以获
得不同的结果对象,一般来说 Builder 模式中对象不是直接返回的。而在 AbstractFactory 模
式中对象是直接返回的, AbstractFactory 模式强调的是为创建多个相互依赖的对象提供一个
同一的接口。
参考文章:Java 大白话讲解设计模式之 -- 建造者(Builder)模式 - 简书
部分内容和示意图来自书:二十三种设计模式