前言
在日常的生活中,我们可以经常看到建造者模式的影子。比如,建造房子,那么房子就是一个产品,房子由门,窗,墙,地板等部门组成。然后包工头在建造房子的时候就根据设计好的图纸来建造,但是包工头并不是亲自来建造房子的,而是通过指挥工人来施工。再比如组装电脑,可以根据不同的厂商来组装成不同类型的包括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、如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大