建造者模式

<image>

在面向对象编程中，建造者模式（builder pattern），也译为生成器模式，是一种对象构建设计模式。它可以将复杂对象的建造过程抽象出来（抽象类别），使这个抽象过程的不同实现方法可以构造出不同表现（属性）的对象。

## 概述

建造者模式所适用的情况：当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式之时；当构造过程必须允许被构造的对象有不同的表示之时。建造者模式的效果：可以改变一个产品的内部表示，将构造代码和表示代码分开，可对构造过程进行更精细的控制。

它需要注意如下一些问题。

- 装配和构造接口：建造者逐步的构造它们的产品，因此建造者界面必须足够普遍，以便为各种类型的具体建造者构造产品。
- 没有抽象类：通常情况下，由具体建造者生成的产品，它们的表示相差是如此之大以至于给不同的产品以公共父类没有太大意思。
- 在建造者中预设的方法为空：定义为空方法可以使客户只重定义他们所感兴趣的操作。

抽象工厂模式与建造者相似，因为它也可以创建复杂对象。主要的区别是建造者模式着重于一步步构造一个复杂对象。而抽象工厂模式着重于多个系列的产品对象（简单的或是复杂的）。建造者在最后的一步返回产品，而对于抽象工厂来说，产品是立即返回的。合成模式的复杂对象通常是可用建造者生成的。

## 结构

<image>

在上面的UML类图中，`Director`类不直接的创建并组装`ProductA1`和`ProductB1`对象。`Director`转而提及`Builder`接口来建造（创建并组装）一个复杂对象的各部分，这使得`Director`独立于哪个具体类要被初始化（哪个表示要被创建）。`Builder1`类通过创建并组装`ProductA1`和`ProductB1`对象来实现`Builder`接口。

UML序列图展示了运行时交互：`Director`对象调用`buildPartA()`于`Builder1`对象之上，它创建并组装`ProductA1`对象。此后，`Director`调用`buildPartB()`于`Builder1`之上，它创建并组装`ProductB1`对象。

### 参与者

- Builder：为创建一个Product对象的各个部件指定抽象接口。
- ConcreteBuilder：实现Builder的接口以构造和装配该产品的各个部件。定义并明确它所创建的表示。提供一个检索产品的接口。
- Director：构造一个使用Builder接口的对象。
- Product：表示被构造的复杂对象。包含定义组成部件的类，包括将这些部件装配成最终产品的接口。ConcreateBuilder创建该产品的内部表示并定义它的装配过程。

客户创建Director对象，并用它所想要的Builder对象进行配置。

- 一旦产品部件被生成，指导者就会通知建造者。
- 建造者处理指导者的请求，并将部件添加到该产品中。
- 客户从建造者中检索产品。

## 范例

### Java

Java例子：

```java
/** "Product" */
class Pizza {
    private String dough = "";
    private String sauce = "";
    private String topping = "";
 
    public void setDough (String dough)     { this.dough = dough; }
    public void setSauce (String sauce)     { this.sauce = sauce; }
    public void setTopping (String topping) { this.topping = topping; }
}
  
/** "Abstract Builder" */
abstract class PizzaBuilder {
    protected Pizza pizza;
 
    public Pizza getPizza() { return pizza; }
    public void createNewPizzaProduct() { pizza = new Pizza(); }
 
    public abstract void buildDough();
    public abstract void buildSauce();
    public abstract void buildTopping();
}
 
/** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
    public void buildDough()   { pizza.setDough("cross"); }
    public void buildSauce()   { pizza.setSauce("mild"); }
    public void buildTopping() { pizza.setTopping("ham+pineapple"); }
}
 
/** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {
    public void buildDough()   { pizza.setDough("pan baked"); }
    public void buildSauce()   { pizza.setSauce("hot"); }
    public void buildTopping() { pizza.setTopping("pepperoni+salami"); }
}
 
 /** "Director" */
class Waiter {
    private PizzaBuilder pizzaBuilder;
 
    public void setPizzaBuilder (PizzaBuilder pb) { pizzaBuilder = pb; }
    public Pizza getPizza() { return pizzaBuilder.getPizza(); }
 
    public void constructPizza() {
        pizzaBuilder.createNewPizzaProduct();
        pizzaBuilder.buildDough();
        pizzaBuilder.buildSauce();
        pizzaBuilder.buildTopping();
    }
}
 
/** A customer ordering a pizza. */
class BuilderExample {
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        PizzaBuilder hawaiianPizzabuilder = new HawaiianPizzaBuilder();
        PizzaBuilder spicyPizzabuilder = new SpicyPizzaBuilder();
 
        waiter.setPizzaBuilder ( hawaiianPizzabuilder );
        waiter.constructPizza();
 
        Pizza pizza = waiter.getPizza();
    }
}
```

### C#

C#例子：

```csharp
// Represents a product created by the builder.
public class Bicycle {
    public Bicycle(string maker, string model, string colour, int height) {
        Maker = maker;
        Model = model;
        Colour = colour;
        Height = height;
    }

    public string Maker { get; set; }
    public string Model { get; set; }
    public int Height { get; set; }
    public string Colour { get; set; }
}

// The builder abstraction.
public interface IBicycleBuilder {
    Bicycle GetResult();

    string Colour { get; set; }
    int Height { get; set; }
}

// Concrete builder implementation.
public class GTBicyclesBuilder : IBicycleBuilder {
    public Bicycle GetResult() {
        return Height == 29 ? new Bicycle("GT Bicycles Inc.", "Avalanche", Colour, Height) : null;
    }

    public string Colour { get; set; }
    public int Height { get; set; }
}

// The director.
public class MountainBikeBuildDirector {
    private IBicycleBuilder _builder;

    public MountainBikeBuildDirector(IBicycleBuilder builder) {
        _builder = builder;
    }

    public void Construct() {
        _builder.Colour = "Red";
        _builder.Height = 29;
    }

    public Bicycle GetResult() {
		return this._builder.GetResult();
	}
}

public class Client {
    public void DoSomethingWithBicycles() {
        var director = new MountainBikeBuildDirector(new GTBicyclesBuilder());
        // Director controls the stepwise creation of product and returns the result.
        director.Construct();
        Bicycle myMountainBike = director.GetResult();
    }
}
```

### Python

Python的例子：

```python
from abc import ABC, abstractmethod
from weakref import WeakKeyDictionary

class Component():
    def __init__(self, name):
        self.name = name
        self.attr_dict = WeakKeyDictionary()
    def __get__(self, obj, objtype=None):
        return (self.attr_dict[obj]
            if obj in self.attr_dict else None)
    def __set__(self, obj, value):
        self.attr_dict[obj] = {'name': self.name} | value
    def __delete__(self, obj):
        if obj in self.attr_dict:
            del self.attr_dict[obj]
    def __call__(self, obj, value=None, *, delete=False):
        if delete is True:
            self.__delete__(obj)
        elif value is None:
            return self.__get__(obj)
        else:
            self.__set__(obj, value)

class Product():
    __part_A = Component('part_A')
    __part_B = Component('part_B')
    __components = [__part_A, __part_B]
    def __len__(self):
        return len(self.__components)
    def __getitem__(self, index):
        return self.__components[index](self)
    def __setitem__(self, index, value):
        self.__components[index](self, value)
    def __delitem__(self, index):
        self.__components[index](self, delete=True)
    @property
    def description(self):
        strlist = [f"{comp['name']}: {comp['builder']}" 
            for comp in self if comp is not None]
        print("{Product: {" + ', '.join(strlist) + "}}")

class Builder(ABC):
    def __init_subclass__(cls, /, params={}, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.params = params
    def __init__(self, **kwargs):
        self.product = Product()
    @abstractmethod
    def build_step_0(self): pass
    @abstractmethod
    def build_step_1(self): pass
    def build(self, **kwargs): 
        self.build_step_0(**kwargs)
        self.build_step_1(**kwargs)
    def get_result(self):
        result, self.product = self.product, None
        return result

class BuilderA(Builder, params={'builder': 'BuilderA'}):
    def build_step_0(self, **kwargs): 
        self.product[0] = type(self).params | kwargs
    def build_step_1(self, **kwargs):
        self.product[1] = type(self).params | kwargs
        
class BuilderB(Builder, params={'builder': 'BuilderB'}):
    def build_step_0(self, **kwargs): 
        self.product[1] = type(self).params | kwargs
    def build_step_1(self, **kwargs):
        self.product[0] = type(self).params | kwargs

class Director():
    def __init__(self, builder_class, **kwargs):
        self.builder_class = builder_class
    def __call__(self, **kwargs):
        self.builder = self.builder_class()
        self.builder.build(kw='')
        result, self.builder = self.builder.get_result(), None
        return result
```

其执行：

```pycon
>>> product1 = Director(BuilderA)()
>>> product1.description
{Product: {part_A: BuilderA, part_B: BuilderA}}
>>> product2 = Director(BuilderB)()
>>> product2.description
{Product: {part_A: BuilderB, part_B: BuilderB}}
```