热门问题
时间线
聊天
视角

建造者模式

来自维基百科,自由的百科全书

建造者模式
Remove ads

建造者模式(英:Builder Pattern),也譯為生成器模式,是一種對象構建設計模式[1]。它可以將複雜對象的建造過程抽象出來(抽象類別),使這個抽象過程的不同實現方法可以構造出不同表現(屬性)的對象。

Thumb
建造者結構

適用性

在以下情況使用建造者模式:

  • 當創建複雜對象的算法應該獨立於該對象的組成部分以及它們的裝配方式時;
  • 當構造過程必須允許被構造的對象有不同的表示時。

結構

Thumb
建造者模式的樣例UML類圖和序列圖[2]

在上面的UML類圖中,Director類不直接的創建並組裝ProductA1ProductB1對象。Director轉而提及Builder接口來建造(創建並組裝)一個複雜對象的各部份,這使得Director獨立於哪個具體類要被初始化(哪個表示要被創建)。Builder1類通過創建並組裝ProductA1ProductB1對象來實現Builder接口。

UML序列圖展示了運行時交互:Director對象調用buildPartA()Builder1對象之上,它創建並組裝ProductA1對象。此後,Director調用buildPartB()Builder1之上,它創建並組裝ProductB1對象。

參與者

  • 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();
   }
}
Remove ads

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();
    }
}
Remove ads

Python

Python的例子:

rom abc import ABC, abstractmethod
from weakref import WeakKeyDictionary

class Component():
    def __init__(self, name, **kwargs):
        self.name = name
        self.weakref_dict = WeakKeyDictionary()
    def __get__(self, obj, objtype=None):
        return (self.weakref_dict[obj]
            if obj in self.weakref_dict else None)
    def __set__(self, obj, value):
        self.weakref_dict[obj] = {'name': self.name} | value

class Product():
    part_A = Component('part_A')
    part_B = Component('part_B')
    def __init__(self, **kwargs): pass
    @property
    def description(self):
        print(f'Product: {self.part_A['name']}, {self.part_A['builder']}; '
            + f'{self.part_B['name']}, {self.part_B['builder']}.')

class Builder(ABC):
    def __init__(self, **kwargs):
        self.product = Product()
    @abstractmethod
    def build_part_A(self): pass
    @abstractmethod
    def build_part_B(self): pass
    def get_result(self):
        result, self.product = self.product, None
        return result

class BuilderA(Builder):
    params = {'builder': 'BuilderA'}
    def build_part_A(self, **kwargs): 
        self.product.part_A = type(self).params | kwargs
    def build_part_B(self, **kwargs):
        self.product.part_B = type(self).params | kwargs
        
class BuilderB(Builder):
    params = {'builder': 'BuilderB'}
    def build_part_A(self, **kwargs): 
        self.product.part_A = type(self).params | kwargs
    def build_part_B(self, **kwargs):
        self.product.part_B = type(self).params | kwargs

class Director():
   def __init__(self, Builder, **kwargs):
       self.Builder = Builder
   def construct(self, **kwargs):
       self.builder = self.Builder()
       self.builder.build_part_A(kw='')
       self.builder.build_part_B(kw='')
       result, self.builder = self.builder.get_result(), None
       return result

其執行:

>>> product1 = Director(BuilderA).construct()
>>> product1.description
Product: part_A, BuilderA; part_B, BuilderA.
>>> product2 = Director(BuilderB).construct()
>>> product2.description
Product: part_A, BuilderB; part_B, BuilderB.
Remove ads

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(); 

?>

注意問題

  • 裝配和構造接口
建造者逐步的構造它們的產品。因此建造者介面必須足夠普遍,以便為各種類型的具體建造者構造產品。
  • 沒有抽象類
通常情況下,由具體建造者生成的產品,它們的表示相差是如此之大以至於給不同的產品以公共父類沒有太大意思。
  • 在建造者中預設的方法為空
定義為空方法可以使客戶只重定義他們所感興趣的操作。

效果

  • 它使你可以改變一個產品的內部表示
  • 它將構造代碼和表示代碼分開
  • 它使你可對構造過程進行更精細的控制

相關模式

抽象工廠模式與建造者相似,因為它也可以創建複雜對象。主要的區別是建造者模式着重於一步步構造一個複雜對象。而抽象工廠模式着重於多個系列的產品對象(簡單的或是複雜的)。建造者在最後的一步返回產品,而對於抽象工廠來說,產品是立即返回的。

合成模式通常是用建造者生成的。

引用

參考書目

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads