文章目录
- 七、建造者设计模式
- 7.1 建造者设计模式简介
- 7.2 建造者设计模式的实现
- 7.2.1 案例引入
- 1)UML类图如下:
- 2)建造者设计模式中的角色
- 7.2.2 代码实现
- 7.2.3 建造者模式的链式写法
- 7.2.4 静态内部类实现建造者模式
- 7.3 建造者与工程模式的区别
- 7.4 建造者设计模式的优缺点
七、建造者设计模式
7.1 建造者设计模式简介
当需要创建的对象非常复杂时,我们可以使用接口抽取出某些对象的相同创建过程,将创建过程交由具体的实现类来完成,这样就可以使得相同的创建行为可以创建出不同的对象,分离了创建过程与具体表现,使得创建产品的灵活性大大增加。
建造者设计模式(Builder Pattern):将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示;
- 语义解释:
- 什么是构建:构建就是指对象的创建
- 什么是表示:泛指对象的属性,行为等
- 什么是构建与表示分离:其实就是使用接口来规定其行为,然后使用具体的实现类来创建对象。使用实现类来构建,使用接口来规定其表示行为(达到构建与表示分离)
- 同样的构建过程创建不同的表示:创建的过程由接口来规范,具体创建过程的实现由子类来完成,这样不同的子类使用相同的创建过程可以创建出不同的对象;
7.2 建造者设计模式的实现
7.2.1 案例引入
我们完成某些产品的创建需要N多个步骤(创建过程复杂),这些步骤都趋向于稳定,不会变化(相同的创建过程);
例如我们在组装游戏台式机时,需要安装顶级显卡,性能一般但主频高的CPU;组装商务台式机时,只需要安装一个亮机卡,再加一个顶级CPU;但是都需要安装显卡和CPU以及一些其他部件;创建产品的步骤趋向稳定(都需要安装CPU和显卡等部件),但是需要创建不同的对象表示(游戏台式机和商务台式机);
1)UML类图如下:
2)建造者设计模式中的角色
在建造者设计模式中主要包含有4个角色:
- 1)产品(Product):要创建的复杂对象。
- 2)抽象建造者(Builder):规范要创建对象的步骤,具体的实现由具体的子类来完成。
- 3)具体建造者(ConcreteBuilder):抽象建造者的具体实现,根据不同的业务类型,来具体化创建对象的每个步骤。
- 4)指挥者(Director):调用具体建造者的每一个步骤来完成对象的创建,指挥者并不知道产品的细节;
7.2.2 代码实现
- 电脑类:
package com.pattern.demo01_建造者设计模式;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Computer {
private String memory;
private String cpu;
private String keyBoard;
private String mouse;
}
- 抽象构建者:
package com.pattern.demo01_建造者设计模式;
/**
* @author lscl
* @version 1.0
* @intro: 抽象构建者
*/
public abstract class Builder {
protected Computer computer=new Computer();
// 抽象每一个步骤
public abstract void addMemory();
public abstract void addCPU();
public abstract void addKeyBoard();
public abstract void addMouse();
public abstract Computer createComputer();
}
- 具体构建者-游戏台式机构建者类:
package com.pattern.demo01_建造者设计模式;
/**
* @author lscl
* @version 1.0
* @intro: 游戏台式机构建者
*/
public class GameBuilder extends Builder {
// 实现每一个构建步骤
@Override
public void addMemory() {
computer.setMemory("添加16G内存条!");
}
@Override
public void addCPU() {
computer.setCpu("添加i5 12600K!");
}
@Override
public void addKeyBoard() {
computer.setKeyBoard("添加游戏专用机械键盘!");
}
@Override
public void addMouse() {
computer.setMouse("添加游戏专用宏鼠标!");
}
@Override
public Computer createComputer() {
return computer;
}
}
- 具体构建者-商务台式机构建者类:
package com.pattern.demo01_建造者设计模式;
/**
* @author lscl
* @version 1.0
* @intro: 商务台式机构建者类
*/
public class BusinessBuilder extends Builder {
// 实现每一个构建步骤
@Override
public void addMemory() {
computer.setMemory("添加32G内存条!");
}
@Override
public void addCPU() {
computer.setCpu("添加i9 12900K!");
}
@Override
public void addKeyBoard() {
computer.setKeyBoard("添加办公专用双飞燕键盘!");
}
@Override
public void addMouse() {
computer.setMouse("添加办公专用双飞燕鼠标!");
}
@Override
public Computer createComputer() {
return computer;
}
}
- 指挥者类:
package com.pattern.demo01_建造者设计模式;
/**
* @author lscl
* @version 1.0
* @intro: 指挥者类
*/
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
/**
* 调用每一个步骤来完成对象的构建
*
* @return
*/
public Computer construct() {
builder.addMemory();
builder.addCPU();
builder.addKeyBoard();
builder.addMouse();
return builder.createComputer();
}
}
在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
7.2.3 建造者模式的链式写法
在普通建造者模式中,创建对象的方式被固定在了Director类中,不能再改变,对于一些创建过程需要变化的对象普通建造者模式将会变得难以维护,因此在实际开发中,我们通常使用建造者模式的链式写法来简化对象的创建过程;它允许我们自己定义创建对象的过程,并最终将创建好的对象返回;
- 产品类:
package com.pattern.demo02_链式写法;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Computer {
private String memory;
private String cpu;
private String keyBoard;
private String mouse;
}
- 构建者类:
package com.pattern.demo02_链式写法;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class ComputerBuilder {
private Computer computer=new Computer();
public ComputerBuilder addMemory(String memory) {
computer.setMemory(memory);
return this;
}
public ComputerBuilder addCPU(String cpu) {
computer.setCpu(cpu);
return this;
}
public ComputerBuilder addKeyBoard(String keyBoard) {
computer.setKeyBoard(keyBoard);
return this;
}
public ComputerBuilder addMouse(String mouse) {
computer.setMouse(mouse);
return this;
}
public Computer build() {
return computer;
}
}
- 测试类:
package com.pattern.demo02_链式写法;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01 {
public static void main(String[] args) {
Computer businessComputer = new ComputerBuilder()
.addMemory("16G大内存")
.addCPU("i9 12900K")
.addKeyBoard("双飞燕键盘")
.addMouse("双飞燕鼠标")
.build();
System.out.println(businessComputer);
System.out.println("---------------------");
Computer gameComputer = new ComputerBuilder()
.addMemory("16G大内存")
.addCPU("i9 12900K")
.addKeyBoard("双飞燕键盘")
.addMouse("双飞燕鼠标")
.build();
System.out.println(gameComputer);
}
}
在建造者模式的链式写法中,Demo01测试类充当了Director的角色,将创建对象的步骤灵活化;
7.2.4 静态内部类实现建造者模式
在实际开发中,我们通常会忽略对象创建的复杂性,将对象的创建过程封装好,只需要调用创建对象的某个方法即可获取对象,因此我们会更加倾向于使用工厂设计模式;工厂设计模式不存在Builder和Director。
一般情况下,使用静态内部类的方式来实现建造者模式将会变得非常轻松,这样一个产品类内部自带一个具体的创建对象,使得建造者模式的形式变得更加简洁;
- 产品类:
package com.pattern.demo03_静态内部类;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Computer {
private String memory;
private String cpu;
private String keyBoard;
private String mouse;
public static class Builder {
private Computer computer=new Computer();
public Builder addMemory(String memory) {
computer.setMemory(memory);
return this;
}
public Builder addCPU(String cpu) {
computer.setCpu(cpu);
return this;
}
public Builder addKeyBoard(String keyBoard) {
computer.setKeyBoard(keyBoard);
return this;
}
public Builder addMouse(String mouse) {
computer.setMouse(mouse);
return this;
}
public Computer build() {
return computer;
}
}
}
- 测试类:
package com.pattern.demo03_静态内部类;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01 {
public static void main(String[] args) {
Computer computer = new Computer.Builder()
.addMemory("16G大内存")
.addCPU("i7 12700K")
.addKeyBoard("罗技键盘")
.addMouse("罗技鼠标")
.build();
System.out.println(computer);
}
}
7.3 建造者与工程模式的区别
- 1)建造者注重于构建的顺序,工厂只关注被创建出来的对象
- 2)建造者不仅要知道如何创建对象,而且更加明白这个对象由哪些部件组成,工厂只需要负责把对象创建出来就行,对对象的内部构造并不清晰;
核心:建造者设计模式更加注重于创建对象的过程,而工厂设计模式更加注重于结果
7.4 建造者设计模式的优缺点
- 优点:
- 1)封装性强,构建和表示分离
- 2)扩展性强,建造者直接相互独立,在一定程度上解耦
- 3)便于控制细节,建造者可以对创建过程精确细化而不对其他模块产生任何影响
- 缺点:
- 1)每一个对象的创建都需要一个建造者(Builder)
- 2)如果产品内部发生变化,那么建造者也要同步修改,后期维护成本大;