建造者模式
外觀

建造者模式(英:Builder Pattern),也譯為生成器模式,是一種對象構建設計模式[1]。它可以將複雜對象的建造過程抽象出來(抽象類別),使這個抽象過程的不同實現方法可以構造出不同表現(屬性)的對象。
適用性
[編輯]在以下情況使用建造者模式:
- 當創建複雜對象的算法應該獨立於該對象的組成部分以及它們的裝配方式時;
- 當構造過程必須允許被構造的對象有不同的表示時。
參與者
[編輯]
- Builder
- 為創建一個Product對象的各個部件指定抽象接口。
- ConcreteBuilder
- 實現Builder的接口以構造和裝配該產品的各個部件。
- 定義並明確它所創建的表示。
- 提供一個檢索產品的接口
- Director
- 構造一個使用Builder接口的對象。
- Product
- 表示被構造的複雜對象。ConcreateBuilder創建該產品的內部表示並定義它的裝配過程。
- 包含定義組成部件的類,包括將這些部件裝配成最終產品的接口。
協作
[編輯]客戶創建Director對象,並用它所想要的Builder對象進行配置。
- 一旦產品部件被生成,指導者就會通知建造者。
- 建造者處理指導者的請求,並將部件添加到該產品中。
- 客戶從建造者中檢索產品。
範例
[編輯]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#例子:
// 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的例子:
from abc import ABC, abstractmethod
class Component(ABC):
def __init__(self, name, **kwargs):
self.name = name
self.builder = None
def __get__(self, obj, objtype=None):
return f'{self.name}, {self.builder}'
def __set__(self, obj, value):
self.builder = value[0]
self.parameters = value[1]
self.build()
@abstractmethod
def build(self): pass
class PartA(Component):
def build(self): pass
class PartB(Component):
def build(self): pass
class Product():
part_A = PartA('Component Part A')
part_B = PartB('Component Part B')
def __init__(self, *args, **kwargs): pass
@staticmethod
def assemble(obj): pass
@property
def description(self):
print(f'Product: {self.part_A}; {self.part_B}.')
class Builder(ABC):
def __init__(self, *args, **kwargs):
self.product = Product()
@abstractmethod
def buildPartA(self): pass
@abstractmethod
def buildPartB(self): pass
def getResult(self):
Product.assemble(self.product)
result, self.product = self.product, None
return result
class BuilderA(Builder):
def buildPartA(self):
self.product.part_A = ('Concrete Builder A', {})
def buildPartB(self):
self.product.part_B = ('Concrete Builder A', {})
class BuilderB(Builder):
def buildPartA(self):
self.product.part_A = ('Concrete Builder B', {})
def buildPartB(self):
self.product.part_B = ('Concrete Builder B', {})
class Director():
def __init__(self, Builder, **kwargs):
self.builder = Builder()
def construct(self):
self.builder.buildPartA()
self.builder.buildPartB()
result, self.builder = self.builder.getResult(), None
return result
其執行:
>>> product1 = Director(BuilderA).construct()
>>> product1.description
Product: Component Part A, Concrete Builder A; Component Part B, Concrete Builder A.
>>> product2 = Director(BuilderB).construct()
>>> product2.description
Product: Component Part A, Concrete Builder B; Component Part B, Concrete Builder B.
PHP
[編輯]PHP例子:
<?php
//設計模式:生成器模式
//Coder: rollenc ( http://www.rollenc.com )
interface Builder {
function buildPartA(); //创建部件A比如创建汽车车轮
//创建部件B 比如创建汽车方向盘
function buildPartB();
//创建部件C 比如创建汽车发动机
function buildPartC();
//返回最后组装成品结果 (返回最后装配好的汽车)
//成品的组装过程不在这里进行,而是转移到下面的Director类中进行.
//从而实现了解耦过程和部件
//return Product
function getResult();
}
class Director {
private $builder;
public function __construct($builder ) {
$this->builder = $builder;
}
// 将部件partA partB partC最后组成复杂对象
//这里是将车轮、方向盘和发动机组装成汽车的过程
public function construct() {
$this->builder->buildPartA();
$this->builder->buildPartB();
$this->builder->buildPartC();
}
}
class ConcreteBuilder implements Builder {
public $partA, $partB, $partC;
public function buildPartA() {
echo 'partA is builded' . "\n";
}
public function buildPartB() {
echo 'partB is builded' . "\n";
}
public function buildPartC() {
echo 'partC is builded' . "\n";
}
public function getResult () {
echo 'Return product.' . "\n";
return 1;
}
}
$builder = new ConcreteBuilder();
$director = new Director( $builder );
$director->construct();
$product = $builder->getResult();
?>
注意問題
[編輯]- 裝配和構造接口
- 建造者逐步的構造它們的產品。因此建造者介面必須足夠普遍,以便為各種類型的具體建造者構造產品。
- 沒有抽象類
- 通常情況下,由具體建造者生成的產品,它們的表示相差是如此之大以至於給不同的產品以公共父類沒有太大意思。
- 在建造者中預設的方法為空
- 定義為空方法可以使客戶只重定義他們所感興趣的操作。
效果
[編輯]- 它使你可以改變一個產品的內部表示
- 它將構造代碼和表示代碼分開
- 它使你可對構造過程進行更精細的控制
相關模式
[編輯]抽象工廠模式與建造者相似,因為它也可以創建複雜對象。主要的區別是建造者模式着重於一步步構造一個複雜對象。而抽象工廠模式着重於多個系列的產品對象(簡單的或是複雜的)。建造者在最後的一步返回產品,而對於抽象工廠來說,產品是立即返回的。
組成模式通常是用建造者生成的。
引用
[編輯]- ^ Gamma et al. 1994,第97頁.
- ^ The Builder design pattern - Structure and Collaboration. w3sDesign.com. [2017-08-12].