建造者模式
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
建造者模式是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。用户只需指定需要建造的类型就可以获得对象,建造过程及细节不需要了解。
介绍
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着”一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。
如何解决:将变与不变分离开。
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
应用实例: 1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的”套餐”。 2、JAVA 中的 StringBuilder。3、Lombok中的Builder注解
建造者(Builder)模式包含如下角色:
- 抽象建造者类(Builder):这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的部件对象的创建。
- 具体建造者类(ConcreteBuilder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供产品的实例。
- 产品类(Product):要创建的复杂对象。
- 指挥者类(Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
常规写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| @Data public class Computer { private String motherboard; private String cpu; private String memory; private String disk; private String gpu; private String power; private String heatSink; private String chassis; }
public interface ComputerBuilder { Computer computer = new Computer(); void buildMotherboard(); void buildCpu(); void buildMemory(); void buildDisk(); void buildGpu(); void buildHeatSink(); void buildPower(); void buildChassis(); Computer build(); }
public class AsusComputerBuilder implements ComputerBuilder { @Override public void buildMotherboard() { computer.setMotherboard("Extreme主板"); } @Override public void buildCpu() { computer.setCpu("Inter 12900KS"); } @Override public void buildMemory() { computer.setMemory("芝奇幻峰戟 16G*2"); } @Override public void buildDisk() { computer.setDisk("三星980Pro 2T"); } @Override public void buildGpu() { computer.setGpu("华硕3090Ti 水猛禽"); } @Override public void buildHeatSink() { computer.setHeatSink("龙神二代一体式水冷"); } @Override public void buildPower() { computer.setPower("雷神二代1200W"); } @Override public void buildChassis() { computer.setChassis("太阳神机箱"); } @Override public Computer build() { return computer; } }
@AllArgsConstructor public class ComputerDirector { private ComputerBuilder computerBuilder; public Computer construct() { computerBuilder.buildMotherboard(); computerBuilder.buildCpu(); computerBuilder.buildMemory(); computerBuilder.buildDisk(); computerBuilder.buildGpu(); computerBuilder.buildHeatSink(); computerBuilder.buildPower(); computerBuilder.buildChassis(); return computerBuilder.build(); } } public static void main(String[] args) { ComputerDirector computerDirector = new ComputerDirector(new AsusComputerBuilder()); System.out.println(computerDirector.construct()); }
|
简化写法(指挥构建一体化)
上述示例代码是构建者的常规的用法,指挥类(ComputerDirector)指挥类的构建过程的先后循序,并向调用者返回完成的产品类,但是在有些情况下需要简化系统结构,可以把指挥类和抽象构建者相互结合,于是就有了下面的写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public class SimpleComputerBuilder { private Computer computer = new Computer(); public void buildMotherBoard(String motherBoard){ computer.setMotherboard(motherBoard); } public void buildCpu(String cpu){ computer.setCpu(cpu); } public void buildMemory(String memory){ computer.setMemory(memory); } public void buildDisk(String disk){ computer.setDisk(disk); } public void buildGpu(String gpu){ computer.setGpu(gpu); } public void buildPower(String power){ computer.setPower(power); } public void buildHeatSink(String heatSink){ computer.setHeatSink(heatSink); } public void buildChassis(String chassis){ computer.setChassis(chassis); } public Computer build(){ return computer; } } public static void main(String[] args) { SimpleComputerBuilder simpleComputerBuilder = new SimpleComputerBuilder(); simpleComputerBuilder.buildMotherBoard("Extreme主板"); simpleComputerBuilder.buildCpu("Inter 12900K"); simpleComputerBuilder.buildMemory("芝奇幻峰戟 16G*2"); simpleComputerBuilder.buildDisk("三星980Pro 2T"); simpleComputerBuilder.buildGpu("华硕3090Ti 水猛禽"); simpleComputerBuilder.buildPower("雷神二代1200W"); simpleComputerBuilder.buildHeatSink("龙神二代一体式水冷"); simpleComputerBuilder.buildChassis("太阳神机箱"); System.out.println(simpleComputerBuilder.build()); }
|
可以看到,对比常规写法,这样写确实简化了系统结构,但同时也加重了建造者类的职责,也不是太符合单一职责原则,如果construct() 过于复杂,建议还是封装到 Director 中。
链式写法
Lombok、Mybatis-plus
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public class SimpleComputerBuilder { private Computer computer = new Computer(); public SimpleComputerBuilder buildMotherBoard(String motherBoard){ computer.setMotherboard(motherBoard); return this; } public SimpleComputerBuilder buildCpu(String cpu){ computer.setCpu(cpu); return this; } public SimpleComputerBuilder buildMemory(String memory){ computer.setMemory(memory); return this; } public SimpleComputerBuilder buildDisk(String disk){ computer.setDisk(disk); return this; } public SimpleComputerBuilder buildGpu(String gpu){ computer.setGpu(gpu); return this; } public SimpleComputerBuilder buildPower(String power){ computer.setPower(power); return this; } public SimpleComputerBuilder buildHeatSink(String heatSink){ computer.setHeatSink(heatSink); return this; } public SimpleComputerBuilder buildChassis(String chassis){ computer.setChassis(chassis); return this; } public Computer build(){ return computer; } } public static void main(String[] args) { Computer asusComputer = new SimpleComputerBuilder().buildMotherBoard("Extreme主板") .buildCpu("Inter 12900K") .buildMemory("芝奇幻峰戟 16G*2") .buildDisk("三星980Pro 2T") .buildGpu("华硕3090Ti 水猛禽") .buildPower("雷神二代1200W") .buildHeatSink("龙神二代一体式水冷") .buildChassis("太阳神机箱").build(); System.out.println(asusComputer); }
|
可以看到,其实链式写法与普通写法的区别并不大,只是在建造者类组装部件的时候,同时将建造者类返回即可,使用链式写法使用起来更方便,某种程度上也可以提高开发效率。从软件设计上,对程序员的要求比较高。
总结
适用场景:
- 适用于创建对象需要很多步骤,但是步骤顺序不一定固定。
- 如果一个对象有非常复杂的内部结构(属性),把复杂对象的创建和使用进行分离。
优点:
- 封装性好,创建和使用分离。
- 扩展性好,建造类之间独立、一定程度上解耦。
缺点:
- 产生多余的Builder对象。
- 产品内部发生变化,建造者都要修改,成本较大。
与工厂模式的区别:
- 建造者模式更注重方法的调用顺序,工厂模式更注重创建对象。
- 创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的都一样。
- 关注点不同,工厂模式只需要把对象创建出来就可以了,而建造者模式中不仅要创建出这个对象,还要知道这个对象由哪些部件组成。
- 建造者模式根据建造过程中的顺序不一样,最终的对象部件组成也不一样。
与抽象工厂模式的区别:
- 抽象工厂模式实现对产品族的创建,一个产品族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式则是不需要关心构建过程,只关心什么产品由什么工厂生产即可。
- 建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品。
- 建造者模式所有函数加到一起才能生成一个对象,抽象工厂一个函数生成一个对象