简介
建造者模式在Java中是一个非常常见的设计模式,我们可以在经常看到,比如StringBuilder,HttpRequestBuilder等等。建造者模式是为了解决构造非常复杂的对象而产生的设计模式。它的作用呢是可分步创建复杂对象,并且使用相同的创建代码生成不同的对象,当然了它也保证了创建和使用分离。
实现
首先,举个例子,我现在想要组装一台电脑,电脑有很多部件,应该要怎么实现呢?当然啦,第一反应肯定是创建一个Computer对象,然后把部件填在里面,再new出来就好了。Computer类如下,那么我可以通过构造函数,把所有要的对象都塞进去创建Computer,也可以空的构造函数,然后通过set方法组装Computer。那么为什么不这么做呢?因为如果一个对象只有两三个参数,完全可以这样做的。但是如果有很多参数的话,就会麻烦。另外如果其中的部分参数是可选的,那么就更麻烦一点,可能需要些很多个构造函数来解决此问题。那么建造者模式就是来解决此问题的。
public class Computer {
private String screen;
private String cpu;
private String keyboard;
private String disk;
/**
* 主机
*/
private String engine;
private String cache;
public Computer() {
}
public Computer(String screen, String cpu, String keyboard, String disk, String engine,
String cache) {
this.screen = screen;
this.cpu = cpu;
this.keyboard = keyboard;
this.disk = disk;
this.engine = engine;
this.cache = cache;
}
public String getScreen() {
return screen;
}
public void setScreen(String screen) {
this.screen = screen;
}
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getKeyboard() {
return keyboard;
}
public void setKeyboard(String keyboard) {
this.keyboard = keyboard;
}
public String getDisk() {
return disk;
}
public void setDisk(String disk) {
this.disk = disk;
}
public String getEngine() {
return engine;
}
public void setEngine(String engine) {
this.engine = engine;
}
public String getCache() {
return cache;
}
public void setCache(String cache) {
this.cache = cache;
}
@Override
public String toString() {
System.out.println("computer is combined by : ---" + getCpu() + "--" + getCache() + "---" + getDisk() + "----" + getEngine() + "----" + getKeyboard() + "----" + getScreen());
return super.toString();
}
}
我们先来一个ComputerBuilder
public abstract class ComputerBuilder {
protected Computer computer = new Computer();
public abstract ComputerBuilder buyScreen(String screen);
public abstract ComputerBuilder buyCpu(String cpu);
public abstract ComputerBuilder buyKeyboard(String keyboard);
public abstract ComputerBuilder buyDisk(String disk);
public abstract ComputerBuilder buyEngine(String engine);
public abstract ComputerBuilder buyCache(String cache);
public Computer build() {
return computer;
}
}
再来个CommonComputerBuilder
public class CommonComputerBuilder extends ComputerBuilder {
@Override
public ComputerBuilder buyScreen(String screen) {
computer.setScreen(screen);
return this;
}
@Override
public ComputerBuilder buyCpu(String cpu) {
computer.setCpu(cpu);
return this;
}
@Override
public ComputerBuilder buyKeyboard(String keyboard) {
computer.setKeyboard(keyboard);
return this;
}
@Override
public ComputerBuilder buyDisk(String disk) {
computer.setDisk(disk);
return this;
}
@Override
public ComputerBuilder buyEngine(String engine) {
computer.setEngine(engine);
return this;
}
@Override
public ComputerBuilder buyCache(String cache) {
computer.setCache(cache);
return this;
}
}
那么现在的我想要组装一台电脑,应该怎么实现呢?
public static void main(String[] args) {
//我想组装一台电脑,需要很多配件
CommonComputerBuilder commonComputerBuilder = new CommonComputerBuilder();
Computer computer = commonComputerBuilder.buyCache("huawei cache")
.buyCpu("intel cpu")
.buyEngine("lenovo engine")
.buyDisk("sansung disk")
.buyKeyboard("luoji keyboard")
.buyScreen("xiaomi screen")
.build();
computer.toString();
}
来看下结果
computer is combined by : ---intel cpu--huawei cache---sansung disk----lenovo engine----luoji keyboard----xiaomi screen
这样的话。我就完全按照自己的想法组装了一台电脑,回头再看介绍,我们解决了构建一个复杂对象,并且可分步创建对象,也完成了使用相同创建代码创建不同对象,完美!另外呢,就是对于扩展性的支持,比如我发现我还需要个鼠标,那么只需要在Computer中添加mouse对象,并在builder中增加buyMouse的方法即可。更完美了!
如果看到这,并且你之前学习过建造者模式,可能会困惑这和我平时学习的建造者模式好像有一些不同!是的,没错,是有所不同,而且开始的时候我也困惑。明明代码中的建造者模式就是和我上面说的一样,可是和理论介绍上的建造者模式不一样。那么现在呢,我有一点小小的理解,分享给大家,还是举组装电脑的例子,我是一个程序员,我想组装一台电脑,因为我本身对电脑各个配件都比较了解,那么我就会希望可以高度定制化一台电脑,以满足我的需求,那么CommonComputerBuilder就非常适合我,我可以选择任何类型的配件,来组装我的电脑。但是呢,假设我是个电脑城卖电脑的老板,顾客来到我这里,说希望组装一台电脑,希望可以满足做设计的需求,或者打游戏的需求,那其实呢我是个有经验的老板,对于这两种需求,我都有流程化的配置,推荐给他们。这时候老板就是director,而特定的builder就是需要的,而我无需每次输入参数。我们来看下代码实现:
public abstract class BossComputerBuilder {
protected Computer computer = new Computer();
public abstract BossComputerBuilder buyScreen();
public abstract BossComputerBuilder buyCpu();
public abstract BossComputerBuilder buyKeyboard();
public abstract BossComputerBuilder buyDisk();
public abstract BossComputerBuilder buyEngine();
public abstract BossComputerBuilder buyCache();
public Computer build() {
return computer;
}
}
public class DesignerComputerBuilder extends BossComputerBuilder {
@Override
public BossComputerBuilder buyScreen() {
computer.setScreen("designer screen");
return this;
}
@Override
public BossComputerBuilder buyCpu() {
computer.setCpu("designer cpu");
return this;
}
@Override
public BossComputerBuilder buyKeyboard() {
computer.setKeyboard("designer keyboard");
return this;
}
@Override
public BossComputerBuilder buyDisk() {
computer.setDisk("designer disk");
return this;
}
@Override
public BossComputerBuilder buyEngine() {
computer.setEngine("designer engine");
return this;
}
@Override
public BossComputerBuilder buyCache() {
computer.setCache("designer cache");
return this;
}
}
public class GameComputerBuilder extends BossComputerBuilder {
@Override
public BossComputerBuilder buyScreen() {
computer.setScreen("game screen");
return this;
}
@Override
public BossComputerBuilder buyCpu() {
computer.setCpu("game cpu");
return this;
}
@Override
public BossComputerBuilder buyKeyboard() {
computer.setKeyboard("game keyboard");
return this;
}
@Override
public BossComputerBuilder buyDisk() {
computer.setDisk("game disk");
return this;
}
@Override
public BossComputerBuilder buyEngine() {
computer.setEngine("game engine");
return this;
}
@Override
public BossComputerBuilder buyCache() {
computer.setCache("game cache");
return this;
}
}
public class BossDirector {
private BossComputerBuilder bossComputerBuilder;
public BossDirector(BossComputerBuilder bossComputerBuilder) {
this.bossComputerBuilder = bossComputerBuilder;
}
public Computer assembleComputer() {
return bossComputerBuilder.buyCache()
.buyCpu()
.buyScreen()
.buyKeyboard()
.buyEngine()
.buyDisk()
.build();
}
}
作为电脑城老板,我有两条很固定的业务,那就是游戏电脑和设计师电脑组装,我会先让员工按照固定流程购买指定配件,也就是DesignerComputerBuilder和GameComputerBuilder,然后到我这里BossDirector这里进行组装,我能清晰的看到组装流程和实现(这也是优势之一
),并且我这里是不关心组装出来的电脑是什么类型。组装完成了,我们先来看下结果:
computer is combined by : ---game cpu--game cache---game disk----game engine----game keyboard----game screen
computer is combined by : ---designer cpu--designer cache---designer disk----designer engine----designer keyboard----designer screen
所以从这里,我们也能感受到传统建造者模式的另一个优势:特定建造者固定,无法进行修改,减少出现差错的可能性,意思就是我们使用GameComputerBuilder构建的电脑不会出现设计师的配件。当然啦,固定的缺点就是不够灵活。
总结
回归定义,设计模式是一套通用的可复用的解决方案,用来解决在软件设计过程中产生的通用问题。设计模式从来不是一成不变的,永远都需要结合实际情况去做变通。针对需要高灵活性的场景,第一种模式更加适用;而针对变化较少的场景,则第二种模式会更加清晰。