建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
话不多说,上demo
先构建一个电脑实体类
public class Computer {
private String cpu;
private String gpu;
private String Hd;
private String RAM;
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getGpu() {
return gpu;
}
public void setGpu(String gpu) {
this.gpu = gpu;
}
public String getHd() {
return Hd;
}
public void setHd(String hd) {
Hd = hd;
}
public String getRAM() {
return RAM;
}
public void setRAM(String RAM) {
this.RAM = RAM;
}
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", gpu='" + gpu + '\'' +
", Hd='" + Hd + '\'' +
", RAM='" + RAM + '\'' +
'}';
}
}
此时,如果我们要组装一台电脑
public class negtive_01 {
public static void main(String[] args) {
Computer computer_01 = new Computer();
computer_01.setCpu("9700k");
computer_01.setGpu("gtx2080ti");
computer_01.setHd("SSD--1T");
computer_01.setRAM("32G");
Computer computer_02 = new Computer();
computer_02.setCpu("9600k");
computer_02.setGpu("gtx1080ti");
computer_02.setHd("SSD--500G");
computer_02.setRAM("16G");
System.out.println(computer_02);
System.out.println(computer_01);
}
}
很明显,这违反了迪米特法则,即最少知道原则,为了解决这个问题,我们可以在服务器端先对这个复杂的组装过程进行封装
public class negtive_02 {
/*=============服务端==========================*/
static class HighComputerBuilder {
private Computer computer = new Computer();
public Computer build() {
computer.setCpu("9700k");
computer.setGpu("gtx2080ti");
computer.setHd("SSD--1T");
computer.setRAM("32G");
return computer;
}
}
static class High_02ComputerBuilder {
private Computer computer = new Computer();
public Computer build() {
computer.setCpu("9600k");
computer.setGpu("gtx1080ti");
computer.setHd("SSD--500G");
computer.setRAM("16G");
return computer;
}
}
/*=====================客户端===============================*/
public static void main(String[] args) {
HighComputerBuilder builder_01 = new HighComputerBuilder();
Computer computer_01 =builder_01.build();
High_02ComputerBuilder builder_02 = new High_02ComputerBuilder();
Computer computer_02 =builder_02.build();
System.out.println(computer_01);
System.out.println(computer_02);
}
}
但是问题又来了,大量重复的代码会导致容错率变低,使得建造组装的过程不稳定,如果服务器少配置了一个参数怎么办?不过这并不是什么问题,有点经验的程序猿都知道,再抽象一个类就好了嘛。这就演变出了建造者模式的雏形,我们看看代码实现:
public class negtive_03 {
/*=============服务端==========================*/
interface ComputerBuilder{
Computer build();
void setCpu();
void setGpu();
void setHd();
void setRAM();
}
static class HighComputerBuilder implements ComputerBuilder{
private Computer computer = new Computer();
@Override
public Computer build() {
return computer;
}
@Override
public void setCpu() {
computer.setCpu("9700k");
}
@Override
public void setGpu() {
computer.setGpu("gtx2080ti");
}
@Override
public void setHd() {
computer.setHd("SSD--1T");
}
@Override
public void setRAM() {
computer.setRAM("32G");
}
}
static class High_02ComputerBuilder implements ComputerBuilder{
private Computer computer = new Computer();
@Override
public Computer build() {
return computer;
}
@Override
public void setCpu() {
computer.setCpu("9600k");
}
@Override
public void setGpu() {
computer.setGpu("gtx1080ti");
}
@Override
public void setHd() {
computer.setHd("SSD--500G");
}
@Override
public void setRAM() {
computer.setRAM("16G");
}
}
/*==============客户端=====================================*/
public static void main(String[] args) {
HighComputerBuilder builder_01 = new HighComputerBuilder();
builder_01.setCpu();
builder_01.setGpu();
builder_01.setHd();
builder_01.setRAM();
Computer computer_01 =builder_01.build();
High_02ComputerBuilder builder_02 = new High_02ComputerBuilder();
builder_02.setCpu();
builder_02.setGpu();
builder_02.setHd();
builder_02.setRAM();
Computer computer_02 =builder_02.build();
System.out.println(computer_01);
System.out.println(computer_02);
}
}
问题看似解决了,不过小伙伴仔细想想,全权交给客户端来做是不安全的,并且这不又回到违反迪米特法则的原点了吗?
看来这条路走不通了,下面我们来采用建造者模式实现,
public class postive {
/*=============服务端==========================*/
interface ComputerBuilder{
Computer getComputer();
void setCpu();
void setGpu();
void setHd();
void setRAM();
}
static class HighComputerBuilder implements ComputerBuilder {
private Computer computer = new Computer();
@Override
public Computer getComputer() {
return computer;
}
@Override
public void setCpu() {
computer.setCpu("9700k");
}
@Override
public void setGpu() {
computer.setGpu("gtx2080ti");
}
@Override
public void setHd() {
computer.setHd("SSD--1T");
}
@Override
public void setRAM() {
computer.setRAM("32G");
}
}
static class High_02ComputerBuilder implements ComputerBuilder {
private Computer computer = new Computer();
@Override
public Computer getComputer() {
return computer;
}
@Override
public void setCpu() {
computer.setCpu("9600k");
}
@Override
public void setGpu() {
computer.setGpu("gtx1080ti");
}
@Override
public void setHd() {
computer.setHd("SSD--500G");
}
@Override
public void setRAM() {
computer.setRAM("16G");
}
}
//指挥者
static class Director {
public Computer build(ComputerBuilder builder){
builder.setCpu();
builder.setGpu();
builder.setRAM();
builder.setHd();
return builder.getComputer();
}
}
/*==============客户端=====================================*/
public static void main(String[] args) {
Director director = new Director();
Computer computer_01 =director.build(new HighComputerBuilder());
Computer computer_02 =director.build(new High_02ComputerBuilder());
System.out.println(computer_01);
System.out.println(computer_02);
}
}
现在我们封装一个指挥者,让指挥者来做之前客户端需要做的事,然后返回一个客户端需要的对象。此时在需要增加一个不同配置的A_Computer类型计算机,只需要编写一个A_Builder类实现ComputerBuilder接口,再传给指挥者Director进行创建即可得到一个A_Computer类型的Computer对象。符合开闭原则。UML类图如下:
总结
- 模式的应用场景
建造者模式唯一区别于工厂模式的是针对复杂对象的创建。也就是说,如果创建简单对象,通常都是使用工厂模式进行创建,而如果创建复杂对象,就可以考虑使用建造者模式。
当需要创建的产品具备复杂创建过程时,可以抽取出共性创建过程,然后交由具体实现类自定义创建流程,使得同样的创建行为可以生产出不同的产品,分离了创建与表示,使创建产品的灵活性大大增加。
建造者模式主要适用于以下应用场景:
- 相同的方法,不同的执行顺序,产生不同的结果。 多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同。
- 产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用。 初始化一个对象特别复杂,参数多,而且很多参数都具有默认值。
建造者模式和工厂模式的区别
通过前面的学习,我们已经了解了建造者模式,那么它和工厂模式有什么区别呢?
- 建造者模式更加注重方法的调用顺序,工厂模式注重创建对象。
- 创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的对象都一样
- 关注重点不一样,工厂模式只需要把对象创建出来就可以了,而建造者模式不仅要创建出对象,还要知道对象由哪些部件组成。
- 建造者模式根据建造过程中的顺序不一样,最终对象部件组成也不一样。
模式的扩展
建造者(Builder)模式在应用过程中可以根据需要改变,如果创建的产品种类只有一种,只需要一个具体建造者,这时可以省略掉抽象建造者,甚至可以省略掉指挥者角色