建造者模式

建造者模式作为创建型设计模式的一种,提供了一种将复杂对象的构建过程与其表示分离的方法,使得同样的构建过程可以创建不同的表示。


目录

  1. 什么是建造者模式?

  2. 建造者模式的意图

  3. 建造者模式的适用场景

  4. 建造者模式的结构

  5. 建造者模式的实现

  6. 建造者模式的优缺点

  7. 建造者模式的常见误区与解决方案

  8. 建造者模式的扩展与变体

  9. 建造者模式的应用实例

  10. 建造者模式的最佳实践

  11. 总结

  12. 参考资料


1. 什么是建造者模式?

建造者模式是一种创建型设计模式,旨在通过将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。它允许一步步构建一个复杂对象,并且可以根据需要定制其内部组成部分。

关键点:

  • 分步构建:将对象的构建过程分解为多个步骤,每个步骤负责构建对象的一个部分。

  • 封装构建过程:将构建过程封装在建造者类中,客户端无需了解具体的构建细节。

  • 灵活性和可扩展性:通过不同的建造者,可以构建出不同类型的对象。


2. 建造者模式的意图

  • 分离复杂对象的构建与表示:使得同样的构建过程可以创建不同的对象表示。

  • 封装构建逻辑:将对象的构建过程封装在建造者中,简化客户端代码。

  • 提供可定制的构建过程:通过不同的建造者,可以灵活地定制对象的构建过程。

  • 增强系统的可扩展性:添加新的建造者无需修改已有代码,符合开闭原则。


3. 建造者模式的适用场景

  • 需要创建复杂对象:对象的创建过程复杂,包含多个步骤或多个组成部分。

  • 对象的各部分可以独立创建:对象的各个部分可以分开构建,并且可以独立变更。

  • 希望控制对象的创建过程:需要对对象的创建过程进行严格控制,确保对象的一致性。

  • 需要创建不同表示的对象:通过相同的构建过程创建不同类型的对象表示。

示例:

  • 文档生成系统:根据不同格式(如PDF、HTML)生成文档。

  • 复杂图形对象:创建不同类型的图形对象,如建筑图、机械图等。

  • 用户界面组件:根据不同平台(如Windows、MacOS)构建用户界面组件。


4. 建造者模式的结构

建造者模式主要由以下几个角色组成:

  • 产品(Product):表示被构建的复杂对象。

  • 抽象建造者(Builder):声明构建产品各个部分的抽象方法。

  • 具体建造者(ConcreteBuilder):实现抽象建造者接口,完成产品的各个部分的具体构建。

  • 指挥者(Director):负责管理建造者,按照一定的顺序构建产品。

UML 类图示例:

+-------------------+
|      Director     |
+-------------------+
| - builder: Builder|
+-------------------+
| + construct()     |
+-------------------+
         |
         |
+-------------------+
|      Builder      |
+-------------------+
| + buildPartA()    |
| + buildPartB()    |
| + getResult()     |
+-------------------+
         /_\
          |
+-------------------+      +-------------------+
| ConcreteBuilder1  |      | ConcreteBuilder2  |
+-------------------+      +-------------------+
| + buildPartA()    |      | + buildPartA()    |
| + buildPartB()    |      | + buildPartB()    |
| + getResult()     |      | + getResult()     |
+-------------------+      +-------------------+
         |
+-------------------+
|      Product      |
+-------------------+
| - partA           |
| - partB           |
+-------------------+
| + show()          |
+-------------------+

5. 建造者模式的实现

建造者模式的实现可以根据不同的编程语言和具体需求有所差异。以下分别以Java、Python和C#为例,展示基本的建造者模式实现。

5.1. 基本实现

Java 实现

// 产品类
public class Product {
    private String partA;
    private String partB;

    public void setPartA(String partA) {
        this.partA = partA;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    public void show() {
        System.out.println("Product [partA=" + partA + ", partB=" + partB + "]");
    }
}

// 抽象建造者
public abstract class Builder {
    protected Product product = new Product();

    public abstract void buildPartA();
    public abstract void buildPartB();

    public Product getResult() {
        return product;
    }
}

// 具体建造者1
public class ConcreteBuilder1 extends Builder {
    public void buildPartA() {
        product.setPartA("Builder1 PartA");
    }

    public void buildPartB() {
        product.setPartB("Builder1 PartB");
    }
}

// 具体建造者2
public class ConcreteBuilder2 extends Builder {
    public void buildPartA() {
        product.setPartA("Builder2 PartA");
    }

    public void buildPartB() {
        product.setPartB("Builder2 PartB");
    }
}

// 指挥者
public class Director {
    private Builder builder;

    public void setBuilder(Builder builder) {
        this.builder = builder;
    }

    public Product construct() {
        builder.buildPartA();
        builder.buildPartB();
        return builder.getResult();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Director director = new Director();

        Builder builder1 = new ConcreteBuilder1();
        director.setBuilder(builder1);
        Product product1 = director.construct();
        product1.show(); // 输出: Product [partA=Builder1 PartA, partB=Builder1 PartB]

        Builder builder2 = new ConcreteBuilder2();
        director.setBuilder(builder2);
        Product product2 = director.construct();
        product2.show(); // 输出: Product [partA=Builder2 PartA, partB=Builder2 PartB]
    }
}

输出:

Product [partA=Builder1 PartA, partB=Builder1 PartB]
Product [partA=Builder2 PartA, partB=Builder2 PartB]

Python 实现

from abc import ABC, abstractmethod

# 产品类
class Product:
    def __init__(self):
        self.part_a = None
        self.part_b = None

    def set_part_a(self, part_a):
        self.part_a = part_a

    def set_part_b(self, part_b):
        self.part_b = part_b

    def show(self):
        print(f"Product [partA={self.part_a}, partB={self.part_b}]")

# 抽象建造者
class Builder(ABC):
    def __init__(self):
        self.product = Product()

    @abstractmethod
    def build_part_a(self):
        pass

    @abstractmethod
    def build_part_b(self):
        pass

    def get_result(self):
        return self.product

# 具体建造者1
class ConcreteBuilder1(Builder):
    def build_part_a(self):
        self.product.set_part_a("Builder1 PartA")

    def build_part_b(self):
        self.product.set_part_b("Builder1 PartB")

# 具体建造者2
class ConcreteBuilder2(Builder):
    def build_part_a(self):
        self.product.set_part_a("Builder2 PartA")

    def build_part_b(self):
        self.product.set_part_b("Builder2 PartB")

# 指挥者
class Director:
    def __init__(self):
        self.builder = None

    def set_builder(self, builder: Builder):
        self.builder = builder

    def construct(self):
        self.builder.build_part_a()
        self.builder.build_part_b()
        return self.builder.get_result()

# 客户端代码
if __name__ == "__main__":
    director = Director()

    builder1 = ConcreteBuilder1()
    director.set_builder(builder1)
    product1 = director.construct()
    product1.show()  # 输出: Product [partA=Builder1 PartA, partB=Builder1 PartB]

    builder2 = ConcreteBuilder2()
    director.set_builder(builder2)
    product2 = director.construct()
    product2.show()  # 输出: Product [partA=Builder2 PartA, partB=Builder2 PartB]

输出:

Product [partA=Builder1 PartA, partB=Builder1 PartB]
Product [partA=Builder2 PartA, partB=Builder2 PartB]

C# 实现

using System;

// 产品类
public class Product
{
    public string PartA { get; set; }
    public string PartB { get; set; }

    public void Show()
    {
        Console.WriteLine($"Product [PartA={PartA}, PartB={PartB}]");
    }
}

// 抽象建造者
public abstract class Builder
{
    protected Product product = new Product();

    public abstract void BuildPartA();
    public abstract void BuildPartB();

    public Product GetResult()
    {
        return product;
    }
}

// 具体建造者1
public class ConcreteBuilder1 : Builder
{
    public override void BuildPartA()
    {
        product.PartA = "Builder1 PartA";
    }

    public override void BuildPartB()
    {
        product.PartB = "Builder1 PartB";
    }
}

// 具体建造者2
public class ConcreteBuilder2 : Builder
{
    public override void BuildPartA()
    {
        product.PartA = "Builder2 PartA";
    }

    public override void BuildPartB()
    {
        product.PartB = "Builder2 PartB";
    }
}

// 指挥者
public class Director
{
    private Builder builder;

    public void SetBuilder(Builder builder)
    {
        this.builder = builder;
    }

    public Product Construct()
    {
        builder.BuildPartA();
        builder.BuildPartB();
        return builder.GetResult();
    }
}

// 客户端代码
public class Client
{
    public static void Main(string[] args)
    {
        Director director = new Director();

        Builder builder1 = new ConcreteBuilder1();
        director.SetBuilder(builder1);
        Product product1 = director.Construct();
        product1.Show(); // 输出: Product [PartA=Builder1 PartA, PartB=Builder1 PartB]

        Builder builder2 = new ConcreteBuilder2();
        director.SetBuilder(builder2);
        Product product2 = director.Construct();
        product2.Show(); // 输出: Product [PartA=Builder2 PartA, PartB=Builder2 PartB]
    }
}

输出:

Product [PartA=Builder1 PartA, PartB=Builder1 PartB]
Product [PartA=Builder2 PartA, PartB=Builder2 PartB]

5.2. 使用内置库实现

某些编程语言提供了内置的建造者模式实现或支持流畅接口(Fluent Interface),使得建造者模式的实现更加简洁和高效。以下以Python中的链式调用和C#中的流畅接口为例,展示如何使用内置特性实现建造者模式。

Python 使用链式调用实现建造者模式

class Product:
    def __init__(self):
        self.parts = []

    def add(self, part: str):
        self.parts.append(part)

    def show(self):
        print("Product parts:", ", ".join(self.parts))

# 建造者类
class Builder:
    def __init__(self):
        self.product = Product()

    def build_part_a(self):
        self.product.add("PartA")
        return self  # 返回自身,实现链式调用

    def build_part_b(self):
        self.product.add("PartB")
        return self

    def get_result(self):
        return self.product

# 客户端代码
if __name__ == "__main__":
    builder = Builder()
    product = builder.build_part_a().build_part_b().get_result()
    product.show()  # 输出: Product parts: PartA, PartB

输出:

Product parts: PartA, PartB

C# 使用流畅接口实现建造者模式

using System;
using System.Collections.Generic;

// 产品类
public class Product
{
    public List<string> Parts { get; } = new List<string>();

    public void Add(string part)
    {
        Parts.Add(part);
    }

    public void Show()
    {
        Console.WriteLine("Product parts: " + string.Join(", ", Parts));
    }
}

// 建造者类
public class Builder
{
    private Product _product = new Product();

    public Builder BuildPartA()
    {
        _product.Add("PartA");
        return this; // 返回自身,实现链式调用
    }

    public Builder BuildPartB()
    {
        _product.Add("PartB");
        return this;
    }

    public Product GetResult()
    {
        return _product;
    }
}

// 客户端代码
public class Client
{
    public static void Main(string[] args)
    {
        Builder builder = new Builder();
        Product product = builder.BuildPartA().BuildPartB().GetResult();
        product.Show(); // 输出: Product parts: PartA, PartB
    }
}

输出:

Product parts: PartA, PartB

6. 建造者模式的优缺点

优点:

  1. 封装复杂的构建过程:将复杂对象的构建过程封装在建造者中,简化客户端代码。

  2. 分离构建与表示:允许同样的构建过程创建不同的表示,增强系统的灵活性。

  3. 遵循单一职责原则:建造者专注于产品的构建,不涉及产品的表示或其他业务逻辑。

  4. 易于扩展:通过新增具体建造者,可以轻松扩展系统功能,而无需修改已有代码。

  5. 支持流畅接口:建造者模式可以与流畅接口结合,实现链式调用,提升代码的可读性。

缺点:

  1. 增加类的数量:每个具体建造者需要创建一个新的建造者类,可能导致系统中类的数量增加。

  2. 代码复杂性:对于简单的对象创建,使用建造者模式可能显得过于复杂。

  3. 维护成本:随着产品的复杂性增加,建造者类的实现和维护可能变得更加繁琐。


7. 建造者模式的常见误区与解决方案

误区1:建造者模式适用于所有复杂对象的创建场景

  • 事实:建造者模式适用于需要分步骤构建复杂对象的场景,但对于简单对象的创建,直接实例化或使用工厂模式可能更合适。

误区2:建造者模式总能减少代码量

  • 事实:建造者模式通过增加建造者类来封装构建过程,可能会导致类的数量增加,并不一定减少代码量。

误区3:建造者模式无法与其他设计模式结合使用

  • 事实:建造者模式可以与其他设计模式结合使用,如工厂模式、单例模式等,以增强系统的设计能力。

解决方案:

  1. 评估需求:在决定使用建造者模式之前,明确对象的创建复杂性和系统的扩展需求,避免过度设计。

  2. 适度使用:仅在需要分步骤构建复杂对象或需要创建多种表示的场景下使用建造者模式。

  3. 结合其他模式:根据具体需求,将建造者模式与其他设计模式结合使用,发挥各自的优势。

  4. 简化建造者实现:通过流畅接口或内置库特性,简化建造者类的实现,降低系统复杂性。


8. 建造者模式的扩展与变体

多级建造者模式(Multi-level Builder Pattern)

  • 定义:通过多级建造者,将复杂对象的构建过程进一步细分,增强系统的灵活性。

  • 应用场景:需要对对象的构建过程进行更细粒度控制的复杂系统。

建造者工厂模式(Builder Factory Pattern)

  • 定义:结合工厂模式,通过工厂创建建造者实例,进一步提升系统的灵活性和可扩展性。

  • 应用场景:系统需要动态选择和创建不同建造者的场景。

建造者与原型模式结合

  • 定义:结合原型模式,通过克隆现有的对象并进行部分修改,实现更高效的对象构建。

  • 应用场景:需要频繁创建类似对象,但有少量差异的场景。

流畅接口与建造者模式结合

  • 定义:通过流畅接口实现建造者模式,支持链式调用,提升代码的可读性和可维护性。

  • 应用场景:需要简洁、易读的对象构建过程的场景。


9. 建造者模式的应用实例

实例1:复杂文档生成系统

描述:
在一个文档生成系统中,需要根据不同的格式(如PDF、HTML、Word)生成文档。通过建造者模式,可以定义不同的建造者来生成不同格式的文档。

Java 实现

// 产品类
public class Document {
    private String title;
    private String content;
    private String footer;

    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setFooter(String footer) {
        this.footer = footer;
    }

    public void show() {
        System.out.println("Title: " + title);
        System.out.println("Content: " + content);
        System.out.println("Footer: " + footer);
    }
}

// 抽象建造者
public abstract class DocumentBuilder {
    protected Document document = new Document();

    public abstract void buildTitle();
    public abstract void buildContent();
    public abstract void buildFooter();

    public Document getResult() {
        return document;
    }
}

// 具体建造者1 - PDF文档
public class PDFDocumentBuilder extends DocumentBuilder {
    public void buildTitle() {
        document.setTitle("PDF Document Title");
    }

    public void buildContent() {
        document.setContent("This is the content of the PDF document.");
    }

    public void buildFooter() {
        document.setFooter("PDF Footer");
    }
}

// 具体建造者2 - HTML文档
public class HTMLDocumentBuilder extends DocumentBuilder {
    public void buildTitle() {
        document.setTitle("<h1>HTML Document Title</h1>");
    }

    public void buildContent() {
        document.setContent("<p>This is the content of the HTML document.</p>");
    }

    public void buildFooter() {
        document.setFooter("<footer>HTML Footer</footer>");
    }
}

// 指挥者
public class Director {
    private DocumentBuilder builder;

    public void setBuilder(DocumentBuilder builder) {
        this.builder = builder;
    }

    public Document construct() {
        builder.buildTitle();
        builder.buildContent();
        builder.buildFooter();
        return builder.getResult();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Director director = new Director();

        DocumentBuilder pdfBuilder = new PDFDocumentBuilder();
        director.setBuilder(pdfBuilder);
        Document pdfDoc = director.construct();
        pdfDoc.show();

        DocumentBuilder htmlBuilder = new HTMLDocumentBuilder();
        director.setBuilder(htmlBuilder);
        Document htmlDoc = director.construct();
        htmlDoc.show();
    }
}

输出:

Title: PDF Document Title
Content: This is the content of the PDF document.
Footer: PDF Footer
Title: <h1>HTML Document Title</h1>
Content: <p>This is the content of the HTML document.</p>
Footer: <footer>HTML Footer</footer>

实例2:建造者模式与流畅接口结合的汽车构建

描述:
在一个汽车制造系统中,通过建造者模式结合流畅接口,实现一步步构建汽车对象,并支持不同配置的汽车构建。

Python 实现

class Car:
    def __init__(self):
        self.make = None
        self.model = None
        self.color = None
        self.engine = None

    def show(self):
        print(f"Car [Make={self.make}, Model={self.model}, Color={self.color}, Engine={self.engine}]")

# 建造者类
class CarBuilder:
    def __init__(self):
        self.car = Car()

    def set_make(self, make: str):
        self.car.make = make
        return self  # 返回自身,实现链式调用

    def set_model(self, model: str):
        self.car.model = model
        return self

    def set_color(self, color: str):
        self.car.color = color
        return self

    def set_engine(self, engine: str):
        self.car.engine = engine
        return self

    def build(self):
        return self.car

# 客户端代码
if __name__ == "__main__":
    builder = CarBuilder()
    car = builder.set_make("Toyota").set_model("Corolla").set_color("Red").set_engine("V4").build()
    car.show()  # 输出: Car [Make=Toyota, Model=Corolla, Color=Red, Engine=V4]

输出:

Car [Make=Toyota, Model=Corolla, Color=Red, Engine=V4]

实例3:C# 中的建造者模式应用于房屋建造

描述:
在一个房屋建造系统中,通过建造者模式定义不同类型的房屋建造者,按步骤构建房屋的各个部分。

C# 实现

using System;

// 产品类
public class House
{
    public string Foundation { get; set; }
    public string Structure { get; set; }
    public string Roof { get; set; }

    public void Show()
    {
        Console.WriteLine($"House [Foundation={Foundation}, Structure={Structure}, Roof={Roof}]");
    }
}

// 抽象建造者
public abstract class HouseBuilder
{
    protected House house = new House();

    public abstract void BuildFoundation();
    public abstract void BuildStructure();
    public abstract void BuildRoof();

    public House GetHouse()
    {
        return house;
    }
}

// 具体建造者1 - 木结构房屋
public class WoodenHouseBuilder : HouseBuilder
{
    public override void BuildFoundation()
    {
        house.Foundation = "Wooden Foundation";
    }

    public override void BuildStructure()
    {
        house.Structure = "Wooden Structure";
    }

    public override void BuildRoof()
    {
        house.Roof = "Wooden Roof";
    }
}

// 具体建造者2 - 石结构房屋
public class StoneHouseBuilder : HouseBuilder
{
    public override void BuildFoundation()
    {
        house.Foundation = "Stone Foundation";
    }

    public override void BuildStructure()
    {
        house.Structure = "Stone Structure";
    }

    public override void BuildRoof()
    {
        house.Roof = "Stone Roof";
    }
}

// 指挥者
public class Director
{
    private HouseBuilder builder;

    public void SetBuilder(HouseBuilder builder)
    {
        this.builder = builder;
    }

    public House Construct()
    {
        builder.BuildFoundation();
        builder.BuildStructure();
        builder.BuildRoof();
        return builder.GetHouse();
    }
}

// 客户端代码
public class Client
{
    public static void Main(string[] args)
    {
        Director director = new Director();

        HouseBuilder woodenBuilder = new WoodenHouseBuilder();
        director.SetBuilder(woodenBuilder);
        House woodenHouse = director.Construct();
        woodenHouse.Show(); // 输出: House [Foundation=Wooden Foundation, Structure=Wooden Structure, Roof=Wooden Roof]

        HouseBuilder stoneBuilder = new StoneHouseBuilder();
        director.SetBuilder(stoneBuilder);
        House stoneHouse = director.Construct();
        stoneHouse.Show(); // 输出: House [Foundation=Stone Foundation, Structure=Stone Structure, Roof=Stone Roof]
    }
}

输出:

House [Foundation=Wooden Foundation, Structure=Wooden Structure, Roof=Wooden Roof]
House [Foundation=Stone Foundation, Structure=Stone Structure, Roof=Stone Roof]

6. 建造者模式的优缺点

优点:

  1. 封装复杂的构建过程:将复杂对象的构建过程封装在建造者中,简化客户端代码。

  2. 分离构建与表示:允许同样的构建过程创建不同的表示,增强系统的灵活性。

  3. 遵循单一职责原则:建造者专注于产品的构建,不涉及产品的表示或其他业务逻辑。

  4. 易于扩展:通过新增具体建造者,可以轻松扩展系统功能,而无需修改已有代码。

  5. 支持流畅接口:建造者模式可以与流畅接口结合,实现链式调用,提升代码的可读性。

缺点:

  1. 增加类的数量:每个具体建造者需要创建一个新的建造者类,可能导致系统中类的数量增加。

  2. 代码复杂性:对于简单的对象创建,使用建造者模式可能显得过于复杂。

  3. 维护成本:随着产品的复杂性增加,建造者类的实现和维护可能变得更加繁琐。


7. 建造者模式的常见误区与解决方案

误区1:建造者模式适用于所有复杂对象的创建场景

  • 事实:建造者模式适用于需要分步骤构建复杂对象的场景,但对于简单对象的创建,直接实例化或使用工厂模式可能更合适。

误区2:建造者模式总能减少代码量

  • 事实:建造者模式通过增加建造者类来封装构建过程,可能会导致类的数量增加,并不一定减少代码量。

误区3:建造者模式无法与其他设计模式结合使用

  • 事实:建造者模式可以与其他设计模式结合使用,如工厂模式、单例模式等,以增强系统的设计能力。

解决方案:

  1. 评估需求:在决定使用建造者模式之前,明确对象的创建复杂性和系统的扩展需求,避免过度设计。

  2. 适度使用:仅在需要分步骤构建复杂对象或需要创建多种表示的场景下使用建造者模式。

  3. 结合其他模式:根据具体需求,将建造者模式与其他设计模式结合使用,发挥各自的优势。

  4. 简化建造者实现:通过流畅接口或内置库特性,简化建造者类的实现,降低系统复杂性。


8. 建造者模式的扩展与变体

多级建造者模式(Multi-level Builder Pattern)

  • 定义:通过多级建造者,将复杂对象的构建过程进一步细分,增强系统的灵活性。

  • 应用场景:需要对对象的构建过程进行更细粒度控制的复杂系统。

建造者工厂模式(Builder Factory Pattern)

  • 定义:结合工厂模式,通过工厂创建建造者实例,进一步提升系统的灵活性和可扩展性。

  • 应用场景:系统需要动态选择和创建不同建造者的场景。

建造者与原型模式结合

  • 定义:结合原型模式,通过克隆现有的对象并进行部分修改,实现更高效的对象构建。

  • 应用场景:需要频繁创建类似对象,但有少量差异的场景。

流畅接口与建造者模式结合

  • 定义:通过流畅接口实现建造者模式,支持链式调用,提升代码的可读性和可维护性。

  • 应用场景:需要简洁、易读的对象构建过程的场景。


9. 建造者模式的应用实例

实例1:复杂文档生成系统

描述:
在一个文档生成系统中,需要根据不同的格式(如PDF、HTML、Word)生成文档。通过建造者模式,可以定义不同的建造者来生成不同格式的文档。

Java 实现

// 产品类
public class Document {
    private String title;
    private String content;
    private String footer;

    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setFooter(String footer) {
        this.footer = footer;
    }

    public void show() {
        System.out.println("Title: " + title);
        System.out.println("Content: " + content);
        System.out.println("Footer: " + footer);
    }
}

// 抽象建造者
public abstract class DocumentBuilder {
    protected Document document = new Document();

    public abstract void buildTitle();
    public abstract void buildContent();
    public abstract void buildFooter();

    public Document getResult() {
        return document;
    }
}

// 具体建造者1 - PDF文档
public class PDFDocumentBuilder extends DocumentBuilder {
    public void buildTitle() {
        document.setTitle("PDF Document Title");
    }

    public void buildContent() {
        document.setContent("This is the content of the PDF document.");
    }

    public void buildFooter() {
        document.setFooter("PDF Footer");
    }
}

// 具体建造者2 - HTML文档
public class HTMLDocumentBuilder extends DocumentBuilder {
    public void buildTitle() {
        document.setTitle("<h1>HTML Document Title</h1>");
    }

    public void buildContent() {
        document.setContent("<p>This is the content of the HTML document.</p>");
    }

    public void buildFooter() {
        document.setFooter("<footer>HTML Footer</footer>");
    }
}

// 指挥者
public class Director {
    private DocumentBuilder builder;

    public void setBuilder(DocumentBuilder builder) {
        this.builder = builder;
    }

    public Document construct() {
        builder.buildTitle();
        builder.buildContent();
        builder.buildFooter();
        return builder.getResult();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Director director = new Director();

        DocumentBuilder pdfBuilder = new PDFDocumentBuilder();
        director.setBuilder(pdfBuilder);
        Document pdfDoc = director.construct();
        pdfDoc.show();

        DocumentBuilder htmlBuilder = new HTMLDocumentBuilder();
        director.setBuilder(htmlBuilder);
        Document htmlDoc = director.construct();
        htmlDoc.show();
    }
}

输出:

Title: PDF Document Title
Content: This is the content of the PDF document.
Footer: PDF Footer
Title: <h1>HTML Document Title</h1>
Content: <p>This is the content of the HTML document.</p>
Footer: <footer>HTML Footer</footer>

实例2:建造者模式与流畅接口结合的汽车构建

描述:
在一个汽车制造系统中,通过建造者模式结合流畅接口,实现一步步构建汽车对象,并支持不同配置的汽车构建。

Python 实现

class Car:
    def __init__(self):
        self.make = None
        self.model = None
        self.color = None
        self.engine = None

    def show(self):
        print(f"Car [Make={self.make}, Model={self.model}, Color={self.color}, Engine={self.engine}]")

# 建造者类
class CarBuilder:
    def __init__(self):
        self.car = Car()

    def set_make(self, make: str):
        self.car.make = make
        return self  # 返回自身,实现链式调用

    def set_model(self, model: str):
        self.car.model = model
        return self

    def set_color(self, color: str):
        self.car.color = color
        return self

    def set_engine(self, engine: str):
        self.car.engine = engine
        return self

    def build(self):
        return self.car

# 客户端代码
if __name__ == "__main__":
    builder = CarBuilder()
    car = builder.set_make("Toyota").set_model("Corolla").set_color("Red").set_engine("V4").build()
    car.show()  # 输出: Car [Make=Toyota, Model=Corolla, Color=Red, Engine=V4]

输出:

Car [Make=Toyota, Model=Corolla, Color=Red, Engine=V4]

实例3:C# 中的建造者模式应用于房屋建造

描述:
在一个房屋建造系统中,通过建造者模式定义不同类型的房屋建造者,按步骤构建房屋的各个部分。

C# 实现

using System;

// 产品类
public class House
{
    public string Foundation { get; set; }
    public string Structure { get; set; }
    public string Roof { get; set; }

    public void Show()
    {
        Console.WriteLine($"House [Foundation={Foundation}, Structure={Structure}, Roof={Roof}]");
    }
}

// 抽象建造者
public abstract class HouseBuilder
{
    protected House house = new House();

    public abstract void BuildFoundation();
    public abstract void BuildStructure();
    public abstract void BuildRoof();

    public House GetHouse()
    {
        return house;
    }
}

// 具体建造者1 - 木结构房屋
public class WoodenHouseBuilder : HouseBuilder
{
    public override void BuildFoundation()
    {
        house.Foundation = "Wooden Foundation";
    }

    public override void BuildStructure()
    {
        house.Structure = "Wooden Structure";
    }

    public override void BuildRoof()
    {
        house.Roof = "Wooden Roof";
    }
}

// 具体建造者2 - 石结构房屋
public class StoneHouseBuilder : HouseBuilder
{
    public override void BuildFoundation()
    {
        house.Foundation = "Stone Foundation";
    }

    public override void BuildStructure()
    {
        house.Structure = "Stone Structure";
    }

    public override void BuildRoof()
    {
        house.Roof = "Stone Roof";
    }
}

// 指挥者
public class Director
{
    private HouseBuilder builder;

    public void SetBuilder(HouseBuilder builder)
    {
        this.builder = builder;
    }

    public House Construct()
    {
        builder.BuildFoundation();
        builder.BuildStructure();
        builder.BuildRoof();
        return builder.GetHouse();
    }
}

// 客户端代码
public class Client
{
    public static void Main(string[] args)
    {
        Director director = new Director();

        HouseBuilder woodenBuilder = new WoodenHouseBuilder();
        director.SetBuilder(woodenBuilder);
        House woodenHouse = director.Construct();
        woodenHouse.Show(); // 输出: House [Foundation=Wooden Foundation, Structure=Wooden Structure, Roof=Wooden Roof]

        HouseBuilder stoneBuilder = new StoneHouseBuilder();
        director.SetBuilder(stoneBuilder);
        House stoneHouse = director.Construct();
        stoneHouse.Show(); // 输出: House [Foundation=Stone Foundation, Structure=Stone Structure, Roof=Stone Roof]
    }
}

输出:

House [Foundation=Wooden Foundation, Structure=Wooden Structure, Roof=Wooden Roof]
House [Foundation=Stone Foundation, Structure=Stone Structure, Roof=Stone Roof]

10. 建造者模式的最佳实践

  1. 明确构建步骤

    • 确定对象的构建步骤,并在建造者中定义这些步骤的抽象方法。

  2. 使用接口或抽象类

    • 定义建造者接口或抽象类,确保不同的建造者实现统一的构建流程。

  3. 支持流畅接口

    • 通过流畅接口(链式调用)简化建造者的使用,提升代码的可读性和可维护性。

  4. 遵循单一职责原则

    • 建造者类仅负责对象的构建,不涉及其他业务逻辑,保持职责单一。

  5. 避免建造者类过于庞大

    • 如果对象的构建过程过于复杂,可以将建造者进一步分解,保持建造者类的简洁性。

  6. 结合指挥者模式

    • 使用指挥者(Director)类来管理建造者,明确构建过程的顺序和步骤。

  7. 考虑使用内置库特性

    • 利用语言的内置特性,如Python的链式调用或C#的流畅接口,简化建造者的实现。

  8. 确保构建过程的一致性

    • 建造者应确保每个构建步骤的正确执行,避免构建出不完整或不一致的对象。

  9. 文档与命名规范

    • 清晰地命名建造者类和构建方法,保持代码的可读性和可维护性。

  10. 测试建造者

    • 为建造者编写单元测试,确保每个构建步骤的正确性和整体构建过程的完整性。


11. 总结

建造者模式是一种强大的创建型设计模式,通过将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。它提高了代码的可读性、可维护性和灵活性,尤其适用于需要分步骤构建复杂对象或需要创建多种表示的场景。然而,过度使用建造者模式可能导致系统结构复杂,增加维护成本。因此,在实际应用中,应根据具体需求合理选择是否使用建造者模式,并遵循最佳实践,确保系统设计的简洁性和高效性。

关键学习点回顾:

  1. 理解建造者模式的核心概念:分步构建、封装构建过程、一对多的构建逻辑。

  2. 掌握不同的实现方式:基本实现、使用内置库特性实现等。

  3. 识别适用的应用场景:复杂对象的构建、多种对象表示、需要严格控制构建过程等。

  4. 认识建造者模式的优缺点:封装构建过程、提高灵活性 vs. 增加类的数量、代码复杂性。

  5. 避免常见误区:合理评估需求,避免过度设计,保持建造者的简洁性和职责单一。

通过理论学习、代码示例和实际应用,您将能够全面掌握建造者模式,并在实际项目中灵活运用,提升自身的设计能力和职业竞争力。


12. 参考资料