Java 设计模式之建造者模式
一、简介
将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
二、实现
在建造者模式中,主要角色如下:
抽象建造者:接口/抽象类 规定要实现复杂对象的创建,但不涉及具体对象的创建。
具体建造者:实现抽象建造者,完成复杂对象的各个部件的具体创建方法,并提供构建好的对象。
指挥者:调用具体建造者来创建复杂对象的各个部分,在指挥者中不涉及具体的产品信息,只负责对象各部分的创建或按照某种顺序创建。
产品:要创建的复杂对象。
举例:
比如我要组装一台电脑,这个电脑由主板,内存,cpu组合而成,而且也是有一定的安装顺序,比如必须要先安装主板再安装cpu,这个过程由指挥者来完成。接下来看代码:
//产品 电脑 public class Computer { private String mainBoard; private String cpu; private String ram; public String getMainBoard() { return mainBoard; } public void setMainBoard(String mainBoard) { this.mainBoard = mainBoard; } 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; } @Override public String toString() { return "Computer{" + "mainBoard='" + mainBoard + '\'' + ", cpu='" + cpu + '\'' + ", ram='" + ram + '\'' + '}'; } }
//抽象建造者类 public abstract class Builder { //持有一个产品电脑 protected Computer computer = new Computer(); abstract void buildMainBoard(String mainBoard); abstract void buildCpu(String cpu); abstract void buildRam(String ram); abstract Computer build(); }
//具体建造者 public class ComputerBuilder extends Builder{ //通过具体建造者 设置产品的属性 @Override void buildMainBoard(String mainBoard) { computer.setMainBoard("主板:"+mainBoard); } @Override void buildCpu(String cpu) { computer.setCpu("cpu:"+cpu); } @Override void buildRam(String ram) { computer.setRam("ram:"+ram); } @Override Computer build() { return computer; } }
//指挥者类 public class ComputerDirector { //持有一个建造者 private Builder builder; public ComputerDirector(Builder builder){ this.builder = builder; } //构建产品 public Computer construct(String mainBoard,String cpu,String ram){ builder.buildMainBoard(mainBoard); builder.buildCpu(cpu); builder.buildRam(ram); return builder.build(); } }
使用:
//创建建造者 ComputerBuilder builder = new ComputerBuilder(); //创建指挥者 ComputerDirector computerDirector = new ComputerDirector(builder); //生产产品 Computer computer = computerDirector.construct("华硕主板","英特尔Cpu","金士顿8G内存"); System.out.println(computer);
输出:
Computer{mainBoard='主板:华硕主板', cpu='cpu:英特尔Cpu', ram='ram:金士顿8G内存'}
至此,就已经通过建造者模式创建出了我们想要的复杂的产品。其中ComputerDirector有着很重要的作用,它用于指导具体构建的过程或顺序,并返回产品类,但是日常开发中,我们通常会简化它,即把指挥者类和抽象建造者结合。
三、扩展
建造者模式除了上面的用途外,在开发中还有一种常用的方法,上面的computerDirector.construct(“华硕主板”,”英特尔Cpu”,”金士顿8G内存”);传入了很多的参数,如果参数更多怎么办?很容易发生错误可读性变差,接下来看看我们的常用写法。
//产品类 public class Computer { private String mainBoard; private String cpu; private String ram; private Computer(Builder builder){ this.mainBoard = builder.mainBoard; this.cpu = builder.cpu; this.ram = builder.ram; } //内部类Builder public static final class Builder{ private String mainBoard; private String cpu; private String ram; public Builder buildMainBoard(String mainBoard){ this.mainBoard = mainBoard; return this; } public Builder buildCpu(String cpu){ this.cpu = cpu; return this; } public Builder buildRam(String ram){ this.ram = ram; return this; } //返回Computer对象 public Computer build(){ return new Computer(this); } } @Override public String toString() { return "Computer{" + "mainBoard='" + mainBoard + '\'' + ", cpu='" + cpu + '\'' + ", ram='" + ram + '\'' + '}'; } }
使用:
Computer computer1 = new Computer.Builder() .buildMainBoard("华硕主板") .buildCpu("英特尔Cpu") .buildRam("金士顿8G内存") .build();
输出:
Computer{mainBoard='华硕主板', cpu='英特尔Cpu', ram='金士顿8G内存'}
这种方式使用起来更方便,提高开发效率,可以链式调用,再使用一些三方的框架时,其中的链式调用就是这样实现的。