前言
在日常的生活中,我们可以经常看到建造者模式的影子。比如,建造房子,那么房子就是一个产品,房子由门,窗,墙,地板等部门组成。然后包工头在建造房子的时候就根据设计好的图纸来建造,但是包工头并不是亲自来建造房子的,而是通过指挥工人来施工。再比如组装电脑,可以根据不同的厂商来组装成不同类型的包括cpu,gpu等都不一样的电脑。
建造者模式定义
建造者模式,也称之为创建者模式,将一个复杂的对象的构建和它的表示分离,使得同样的构建过程可以创建出不同的表示,这样的设计模式称之为建造者模式。建造者模式将一个复杂的对象分解成多个简单的对象,然后利用简单的对象一步步构建出复杂的对象。它是变与不变相互分离,即一个产品的组成部分是相同的,但是每个部分产品确实可以依据具体情况来灵活选择。
建造者模式的应用场景
需要生成的产品对象具有复杂的内部结构,隔离产品构建和表示,比如:
1、Java中的java.lang.StringBuilder、java.lang.StringBuffer类使用到了建造者模式。
2、mybatis 中的SqlSessionFactoryBuilder使用到了建造者模式。
建造者模式的角色
1、产品(product):被创建的复杂对象,内部具有多个属性等,由具体的建造者来构建。比如电脑,房子等都是产品角色。
2、抽象建造者(abstract builder): 抽象建造者是对产品构建过程的规范,比如建造房子需要哪些步骤才可以。类似于房子的设计图纸,所有的房子都是按照图纸建造出来的。
3、具体建造者(concrete builder):具体建造者构建产品过程中每个步骤的具体体现。比如建造房子是需要地板,那么这个地板是用木板还是瓷砖来做的,都是由具体建造者角色来决定的。
4、指挥者(director):指挥者就是根据具体建造者的步骤,依据不同的顺序来构建出具体的产品。比如每个包工头建造的房子的顺序都不一样,有的可以要先砌好墙,然后再砌地板,但是无论顺序怎么样,最终造出来的房子是一样的。
建造者模式UML类图
代码实现
首先,我先用上面组装电脑的例子用代码实现一下。
第一步,创建产品:computer
/** * @InterfaceName: Computer * @description: * @author: rainple * @create: 2020-05-07 12:42 **/ public class Computer { private String gpu; private String cpu; private String ram; private String mainboard; private String power; public String getGpu() { return gpu; } public void setGpu(String gpu) { this.gpu = gpu; } 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; } public String getMainboard() { return mainboard; } public void setMainboard(String mainboard) { this.mainboard = mainboard; } public String getPower() { return power; } public void setPower(String power) { this.power = power; } @Override public String toString() { return "Computer{" + "gpu='" + gpu + '\'' + ", cpu='" + cpu + '\'' + ", ram='" + ram + '\'' + ", mainboard='" + mainboard + '\'' + ", power='" + power + '\'' + '}'; } }
生成抽象Builder类
/** * @className: Builder * @description: * @author: rainple * @create: 2020-05-07 12:45 **/ public abstract class Builder { /** * 组装显卡 */ abstract void buildGpu(); /** * 组装cpu */ abstract void buildCpu(); /** * 组装内存 */ abstract void buildRam(); /** * 组装主板 */ abstract void buildMainboard(); /** * 组装电源 */ abstract void buildPower(); /** * 获取电脑 * @return */ abstract Computer getComputer(); }
创建一个mac电脑
/** * @className: MacComputer * @description: * @author: rainple * @create: 2020-05-07 12:47 **/ public class MacComputerBuilder extends Builder { private Computer computer; public MacComputerBuilder() { computer = new Computer(); } @Override void buildGpu() { computer.setGpu("atx"); System.out.println("mac book is building gpu"); } @Override void buildCpu() { computer.setCpu("intel i7"); System.out.println("mac book is building cpu"); } @Override void buildRam() { computer.setRam("三星"); System.out.println("mac book is building ram"); } @Override void buildMainboard() { computer.setMainboard("microStar"); System.out.println("mac book is building main board"); } @Override void buildPower() { computer.setPower("战斧"); System.out.println("mac book is building power"); } @Override Computer getComputer() { return computer; } }
指挥者
/** * @className: Derector * @description: * @author: rainple * @create: 2020-05-07 12:52 **/ public class Director { private Builder builder; public Director(Builder builder) { this.builder = builder; } public void setBuilder(Builder builder) { this.builder = builder; } /** * 组装电脑,组装的顺序可以不同,但是最终组装出来的电脑是一致的 * @return */ public Computer build() { builder.buildGpu(); builder.buildCpu(); builder.buildMainboard(); builder.buildPower(); builder.buildRam(); return builder.getComputer(); } }
测试
/** * @className: Client * @description: * @author: rainple * @create: 2020-05-07 12:54 **/ public class Client { public static void main(String[] args) { Builder builder = new MacComputerBuilder(); Director director = new Director(builder); Computer build = director.build(); System.out.println(build); } }
//mac book is building gpu
//mac book is building cpu
//mac book is building main board
//mac book is building power
//mac book is building ram
//Computer{gpu='atx', cpu='intel i7', ram='三星', mainboard='microStar', power='战斧'}
当我们在需要创建其它品牌的电脑时,我们只需要集成Builder即可,
/** * @className: HuaweiComputer * @description: * @author: rainple * @create: 2020-05-08 12:42 **/ public class HuaweiComputerBuilder extends Builder { private Computer computer; public HuaweiComputerBuilder() { computer = new Computer(); } @Override void buildGpu() { computer.setGpu("显卡"); } @Override void buildCpu() { computer.setCpu("cpu"); } @Override void buildRam() { computer.setRam("内存"); } @Override void buildMainboard() { computer.setMainboard("主板"); } @Override void buildPower() { computer.setPower("电源"); } @Override Computer getComputer() { return computer; } }
测试
/** * @className: Client * @description: * @author: rainple * @create: 2020-05-07 12:54 **/ public class Client { public static void main(String[] args) { Builder builder = new MacComputerBuilder(); Director director = new Director(builder); Computer build = director.build(); System.out.println(build); director.setBuilder(new HuaweiComputerBuilder()); build = director.build(); System.out.println(build); } }
结果:
mac book is building gpu
mac book is building cpu
mac book is building main board
mac book is building power
mac book is building ram
Computer{gpu='atx', cpu='intel i7', ram='三星', mainboard='microStar', power='战斧'}
Computer{gpu='显卡', cpu='cpu', ram='内存', mainboard='主板', power='电源'}
建造者模式的优缺点
优点:
1、可以分步构建复杂的对象
2、能够解决复杂对象内部结构频繁的需求变动的问题
3、用户新增不同产品时,只需要新增具体的构建者即可,不需要修改原有的产品的构建流程
缺点:
1、建造者模式不适用与存有较大差异的产品对象
2、如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大