代码的建筑师——使用建造者模式构建优雅的对象

104 阅读5分钟

代码的建筑师——使用建造者模式构建优雅的对象

编写代码时,我们通常会有一些对象的构建是非常复杂的,我们的代码可能会非常的繁琐,以至于难以理解和维护。今天我想分享的建造者模式就是解决这一大问题的利器,通过这篇文章,我们将学习如何成为代码的建造师,构建出优雅、灵活的对象实例。

1. 概述

建造者模式是一种较为复杂的创建型模式,它将一个复杂对象的构建与表示分离开来,使得同样的构建过程可以创建不同的表现。客户端无须知道对象的内部组成以及创建的具体细节。

2. 结构

  • Builder: 抽象建造者为创建一个产品对象的各个部件指定抽象接口,一般声明两类方法,一类是buildPartX(),用于创建复杂对象的部件,另一类是getResult(),用于返回创建的复杂对象;
  • ConCreteBuilder: 具体建造者实现了抽象建造者,实现了具体的各个部件的构造和装配方式;
  • Product: 产品角色就是被创建的复杂对象,包含多个组件组成。产品类通常包含设置和获取各个部件的方法;
  • Director: 指挥者又成为导演类,负责使用建造者构建产品,不直接创建产品实例,而是委托给具体的建造者执行构建过程。提供一个构建产品的方法,这个方法包含了构建产品所需的所有步骤;

3. 案例分析

假我们需要生产电脑,我们来使用建造者模式创建一个笔记本电脑。

产品类:(电脑就是复杂对象,电脑类中包含了许多的组件)

 public class Computer {
     private String cpu;
     private String ram;
     private String storge;
     private String graphicsCard;
 ​
     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 getStorge() {
         return storge;
     }
 ​
     public void setStorge(String storge) {
         this.storge = storge;
     }
 ​
     public String getGraphicsCard() {
         return graphicsCard;
     }
 ​
     public void setGraphicsCard(String graphicsCard) {
         this.graphicsCard = graphicsCard;
     }
 ​
     @Override
     public String toString() {
         return "Computer{" +
                 "cpu='" + cpu + ''' +
                 ", ram='" + ram + ''' +
                 ", storge='" + storge + ''' +
                 ", graphicsCard='" + graphicsCard + ''' +
                 '}';
     }
 }

抽象建造者:(抽象建造者中定义了build组件的方法和获取复杂对象的方法)

 public abstract class ComputerBuilder {
     abstract void buildCpu();
 ​
     abstract void buildRam();
 ​
     abstract void buildStorage();
 ​
     abstract void buildGraphicsCard();
 ​
     abstract Computer getComputer();
 }

具体建造者:(实现了抽象建造类中定义的方法,细化具体的建造组件的过程并且提供了返回复杂对象的方式)

 // 具体建造者 —— 笔记本电脑
 public class LaptopBuilder extends ComputerBuilder{
 ​
     private Computer computer;
 ​
     public LaptopBuilder() {
         this.computer = new Computer();
     }
 ​
     @Override
     public void buildCpu() {
          this.computer.setCpu("Intel Core i5");
     }
 ​
     @Override
     public void buildRam() {
         this.computer.setRam("8GB DDR4");
     }
 ​
     @Override
     public void buildStorage() {
         this.computer.setStorge("256GB SSD");
     }
 ​
     @Override
     public void buildGraphicsCard() {
         this.computer.setGraphicsCard("Integrated Graphics");
     }
 ​
     @Override
     public Computer getComputer() {
         return computer;
     }
 }

导演类:(construct方法用于使用一定的方式创建给具体复杂对象增加功能)

 public class ComputerDirector {
     private ComputerBuilder builder;
     
     public ComputerDirector(ComputerBuilder computerBuilder) {
         builder = computerBuilder;
     }
 ​
     public Computer construct() {
         builder.buildCpu(); // 先建造cpu
         builder.buildRam(); // 建造RAM
         builder.buildStorage(); // 建造存储器
         builder.buildGraphicsCard(); // 建造显卡
         return builder.getComputer();
     }
 }

Client:

 public class Client {
     public static void main(String[] args) {
         // 创建一个笔记本电脑的建造者
         ComputerBuilder laptopBuilder = new LaptopBuilder();
         // 创建一个导演
         ComputerDirector computerDirector = new ComputerDirector(laptopBuilder);
         // 导演开始创建笔记本
         Computer laptopComputer = computerDirector.construct();
         // 获取笔记本电脑
         System.out.println(laptopComputer);
     }
 }
 ​

如果我们这个时候想要创建一个台式电脑,我们只需要新增一个具体的建造者对象就好啦~

 //  具体建造者 —— 台式电脑
 public class DesktopBuilder extends ComputerBuilder{
     private Computer computer;
 ​
     public DesktopBuilder() {
         this.computer = new Computer();
     }
 ​
     @Override
     public void buildCpu() {
         this.computer.setCpu("AMD Ryzen 7");
     }
 ​
     @Override
     public void buildRam() {
         this.computer.setRam("16GB DDR4");
     }
 ​
     @Override
     public void buildStorage() {
         this.computer.setStorge("1TB HDD");
     }
 ​
     @Override
     public void buildGraphicsCard() {
         this.computer.setGraphicsCard("NVIDIA GeForce GTX 1660");
     }
 ​
     @Override
     public Computer getComputer() {
         return computer;
     }
 }
 public class Client {
     public static void main(String[] args) {
         // 创建一个笔记本电脑的建造者
         ComputerBuilder laptopBuilder = new LaptopBuilder();
         // 创建一个导演
         ComputerDirector computerDirector = new ComputerDirector(laptopBuilder);
         // 导演开始创建笔记本
         Computer laptopComputer = computerDirector.construct();
         // 获取笔记本电脑
         System.out.println(laptopComputer);
         // 创建一个台式电脑的建造者
         ComputerBuilder desktopBuilder = new DesktopBuilder();
         // 交给导演开始建造
         computerDirector = new ComputerDirector(desktopBuilder);
         // 获取台式电脑
         Computer desktopComputer = computerDirector.construct();
         System.out.println(desktopComputer);
     }
 }

4. UML图

5. 优点和缺点

5.1 优点

  • 分布构建: 建造者模式可以逐步的构建一个复杂的对象。客户端代码可以根据需要调用不同的建造者方法构建不同的部分,实现分布构建;
  • 可配置: 可以根据需要配置产品的构建过程。不同的建造者可以根据不同的方式构建产品,建造者之间相互独立,可以很方便的新增建造者对象,获得不同的产品对象;
  • 隐藏创建复杂性: 客户端创建复杂对象时,你需要了解产品的具体构建过程。隐藏了产品构建的复杂性,使客户端更加简洁;
  • 对象构建灵活: 建造者模式可以在不影响其他部分的情况下更改产品的内部表示。更改产品的构建过程无须更改客户端代码;

5.2 缺点

  • 不适合差异大的产品: 建造者模式创建的产品一般都有很多共同点,内部组成部分相似。如果想要创建的产品之间差异较大,就不适合使用建造者模式;
  • 增加代码复杂性: 建造者模式会引入额外的类,增加了代码的复杂性;

6. 使用场景

  • 构建复杂场景: 需要生成的产品内部结构复杂,通常包含多个成员变量时,建造者模式很有用,可以灵活管理对象构建过程;(写代码时构造器参数过多~~)
  • 变化频繁的对象构建: 如果对象的构建过程经常发生变化,可以根据不同的需求定制产品;
  • 创建不同形式的产品: 如果需要创建各种形式的产品,他们的制造过程相似且差异不大时;