一、简介
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示,将这个对象的创建交给其它对象。建造者模式是一种对象创建型模式
建造者模式定义了一个新的类来构建另一个类的实例,以简化复杂对象的创建
二、模式结构
- 抽象建造者(builder): 接口或者抽象类,定义对象组件建造方法和返回具体对象
- 实际建造者(concreteBuilder): 实现builder
- 管理者(director):负责安排复杂对象的建造次序
- 产品角色(product):建造的产品
三、代码示例
组装一台电脑,使用建造者模式
product
public class Computer {
private String cpu;
private String Memory;
//显卡
private String graphics;
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getMemory() {
return Memory;
}
public void setMemory(String memory) {
Memory = memory;
}
public String getGraphics() {
return graphics;
}
public void setGraphics(String graphics) {
this.graphics = graphics;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", Memory='" + Memory + '\'' +
", graphics='" + graphics + '\'' +
'}';
}
}
builder and concreteBuilder
public interface ComputerBuilder {
void buildCpu();
void buildMemory();
void buildGraphics();
Computer buildComputer();
}
//具体建造者,使用Cpu,内存,显卡的型号在这里指定
public class ComputerBuilderImpl implements ComputerBuilder {
private Computer c = new Computer();
@Override
public void buildCpu() {
c.setCpu("I7");
}
@Override
public void buildMemory() {
c.setMemory("16G");
}
@Override
public void buildGraphics() {
c.setGraphics("GTX 2080");
}
@Override
public Computer buildComputer() {
return c;
}
}
Director
public class Director {
//具体组装过程,可以改变组装顺序
public void build(ComputerBuilder computerBuilder) {
computerBuilder.buildCpu();
computerBuilder.buildMemory();
computerBuilder.buildGraphics();
}
}
测试类
public class Test {
public static void main(String[] args) {
//不使用建造者
Computer c = new Computer();
c.setCpu("I5");
c.setMemory("8G");
c.setGraphics("1080 TI");
System.out.println(c);
//使用建造者,但是不要设计师,这里可以自由选择组装电脑顺序
ComputerBuilder computerBuilder = new ComputerBuilderImpl();
computerBuilder.buildMemory();
computerBuilder.buildCpu();
computerBuilder.buildGraphics();
Computer c1 = computerBuilder.buildComputer();
System.out.println(c1);
//使用建造者模式,完全托管
ComputerBuilder cb = new ComputerBuilderImpl();
Director director = new Director();
director.build(cb);
Computer c2 = cb.buildComputer();
System.out.println(c2);
}
}
执行结果:
Computer{cpu='I5', Memory='8G', graphics='1080 TI'}
Computer{cpu='I7', Memory='16G', graphics='GTX 2080'}
Computer{cpu='I7', Memory='16G', graphics='GTX 2080'}
四、简单建造者
public class Computer {
private String cpu;
private String memory;
private String graphics;
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 getGraphics() {
return graphics;
}
public void setGraphics(String graphics) {
this.graphics = graphics;
}
public static ComputerBuilder createComputerBuilder() {
return new ComputerBuilder();
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", memory='" + memory + '\'' +
", graphics='" + graphics + '\'' +
'}';
}
static class ComputerBuilder {
private Computer c = new Computer();
public ComputerBuilder setCpu(String cpu) {
c.setCpu(cpu);
return this;
}
public ComputerBuilder setMemory(String memory) {
c.setMemory(memory);
return this;
}
public ComputerBuilder setGraphics(String graphics) {
c.setGraphics(graphics);
return this;
}
public Computer buildComputer() {
return c;
}
}
}
测试类
public class Test {
public static void main(String[] args) {
Computer computer = Computer.createComputerBuilder().setCpu("I9").
setMemory("32G").setGraphics("GTX 2080").buildComputer();
System.out.println(computer);
}
}
这种使用内部静态类的写法,省略了指挥者和抽象建造者,这是简单建造者模式的实现,可以让我们使用链式写法创建对象,看起来会简单方便很多,但是需要写过多额外代码,尤其在类属性过多的情况下。
解决上述问题的方法就是使用Lombok插件,项目中引入Lombok插件后,直接在类上加上@Builder注解,就可以直接使用链式创建对象,这种链式写法在Scala中大量使用,用起来确实很爽。
五、使用场景
- 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
- 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
- 对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类中。
- 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品
六、优缺点
优点:
- 在建造者模式中, 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
- 一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象
- 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程
- 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则
缺点:
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。