设计模式(构建者模式)

建造者设计模式详解

建造者模式(Builder Pattern)是一种创建型设计模式,它允许我们分步骤创建复杂对象。这种模式特别适合那些需要多个步骤才能构建出来的、有很多配置选项的对象。

为什么需要建造者模式?

想象一下,我们需要创建一个House对象,这个房子有墙壁、门、窗户、屋顶等组件。传统方式可能是这样的:

House house = new House(4, 2, 6, true, "红砖", "木头", "瓷砖");

这种方式有几个问题:

  1. 参数过多:构造函数的参数太多,容易搞混
  2. 参数顺序:必须记住参数的准确顺序
  3. 可选参数:如果某些参数是可选的,可能需要创建多个构造函数

建造者模式如何解决这些问题?

建造者模式将对象的构造过程抽象为独立的步骤,每个步骤都可以被单独调用,最后一次性创建完整的对象。

图解建造者模式

让我们通过一个图例来理解建造者模式的结构:

┌───────────────┐      uses      ┌───────────────┐
│    Client     │───────────────▶│    Director   │
└───────────────┘                └───────┬───────┘
                                         │
                                         │ uses
                                         ▼
┌───────────────┐      builds    ┌───────────────┐
│    Product    │◀───────────────│    Builder    │
└───────────────┘                └───────┬───────┘
                                         │
                                         │ implements
                                         ▼
                                 ┌───────────────┐
                                 │ConcreteBuilder│
                                 └───────────────┘

这个图解展示了以下组件:

  • Product:最终要创建的复杂对象
  • Builder:定义创建Product对象的抽象接口
  • ConcreteBuilder:实现Builder接口的具体类
  • Director:调用Builder接口创建最终的Product对象

建造房子的例子

让我们用建造房子作为例子,看看建造者模式如何工作:

           创建过程
┌─────────────────────────────────┐
│                                 │
│   ┌─────┐    ┌─────┐    ┌─────┐ │     ┌───────────┐
│   │     │    │     │    │     │ │     │           │
│   │墙壁 │───▶│门窗 │───▶│屋顶 │─┼────▶│  完整房屋  │
│   │     │    │     │    │     │ │     │           │
│   └─────┘    └─────┘    └─────┘ │     └───────────┘
│                                 │
└─────────────────────────────────┘

代码实现

下面是一个Java代码实现的例子:

// 1. 产品类
class House {
    private String foundation;
    private String walls;
    private String roof;
    private int windows;
    private int doors;
    private boolean hasGarage;
    private boolean hasSwimmingPool;
    private boolean hasGarden;

    public String toString() {
        return "House with " + walls + " walls, " + roof + " roof, " + 
               windows + " windows, " + doors + " doors" + 
               (hasGarage ? ", with garage" : ", without garage") +
               (hasSwimmingPool ? ", with swimming pool" : ", without swimming pool") +
               (hasGarden ? ", with garden" : ", without garden");
    }

    // Getter 方法...
    
    // 私有构造函数,只能通过Builder访问
    private House() {}
    
    // 静态内部Builder类
    public static class Builder {
        private House house;
        
        public Builder() {
            house = new House();
        }
        
        public Builder foundation(String foundation) {
            house.foundation = foundation;
            return this;
        }
        
        public Builder walls(String walls) {
            house.walls = walls;
            return this;
        }
        
        public Builder roof(String roof) {
            house.roof = roof;
            return this;
        }
        
        public Builder windows(int windows) {
            house.windows = windows;
            return this;
        }
        
        public Builder doors(int doors) {
            house.doors = doors;
            return this;
        }
        
        public Builder garage(boolean hasGarage) {
            house.hasGarage = hasGarage;
            return this;
        }
        
        public Builder swimmingPool(boolean hasSwimmingPool) {
            house.hasSwimmingPool = hasSwimmingPool;
            return this;
        }
        
        public Builder garden(boolean hasGarden) {
            house.hasGarden = hasGarden;
            return this;
        }
        
        public House build() {
            return house;
        }
    }
}

// 2. 指导者类(可选)
class HouseDirector {
    public House constructLuxuryHouse(House.Builder builder) {
        return builder
            .foundation("混凝土")
            .walls("砖墙")
            .roof("瓦片屋顶")
            .windows(8)
            .doors(4)
            .garage(true)
            .swimmingPool(true)
            .garden(true)
            .build();
    }
    
    public House constructSimpleHouse(House.Builder builder) {
        return builder
            .foundation("混凝土")
            .walls("砖墙")
            .roof("简易屋顶")
            .windows(4)
            .doors(2)
            .garage(false)
            .swimmingPool(false)
            .garden(false)
            .build();
    }
}

// 3. 客户端代码
public class BuilderDemo {
    public static void main(String[] args) {
        // 使用Builder直接构建
        House house1 = new House.Builder()
            .walls("砖墙")
            .roof("瓦片屋顶")
            .windows(6)
            .doors(2)
            .garage(true)
            .build();
            
        System.out.println("自定义房屋: " + house1);
        
        // 使用Director构建预定义房屋类型
        HouseDirector director = new HouseDirector();
        House luxuryHouse = director.constructLuxuryHouse(new House.Builder());
        House simpleHouse = director.constructSimpleHouse(new House.Builder());
        
        System.out.println("豪华房屋: " + luxuryHouse);
        System.out.println("简易房屋: " + simpleHouse);
    }
}

建造者模式的流程图

以下是建造者模式的实际工作流程图:

┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│             │  (1)    │             │  (2)    │             │
│   Client    │────────▶│   Builder   │────────▶│   Product   │
│             │  创建    │             │  构建    │             │
└─────────────┘         └──────┬──────┘         └─────────────┘
                               │
                               │ (1.1) 设置属性
                               │
                               ▼
                        ┌─────────────┐
                        │  Director   │
                        │  (可选)     │
                        └─────────────┘
  1. 客户端创建一个Builder对象
  2. 客户端直接或通过Director配置Builder
  3. 客户端调用Builder的build()方法获取最终产品

建造者模式的优点

  1. 分步构建:可以一步一步创建复杂对象
  2. 流式接口:使用方法链提供流畅的API
  3. 参数清晰:每个方法名清晰表明设置的是什么属性
  4. 不变性:可以创建不可变对象
  5. 可选参数:轻松处理大量可选参数

建造者模式的应用场景

  1. 复杂对象创建:当对象有很多属性,特别是有可选属性时
  2. 不可变对象:需要创建不可变对象时
  3. 多步骤构建:对象需要多步骤才能完成构建时
  4. 配置对象:需要创建具有多种配置的对象时

现实世界中的建造者模式

Java中的几个常见例子:

  • StringBuilderStringBuffer
  • DocumentBuilder 在Java的XML处理中
  • Java 8中Stream API的链式调用

结论

建造者模式是一种强大的设计模式,尤其适合创建复杂对象。它将对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。这种模式提高了代码的可读性、可维护性,并且提供了一种创建复杂对象的清晰方式。

当你面对具有许多属性的复杂对象时,考虑使用建造者模式,它可以让你的代码更加整洁和灵活。

你可能感兴趣的:(设计模式)