Separate the construction of a complex object from its representation so that the same construction process can create different representations.(將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。)
《設計模式之禪》
以建立不一樣口味 pizza 的過程爲例,Margarita Pizza 和 CreamyBacon Pizza,而 Waiter 做爲一個 Director, Pizza 是最終實現出來的產品。java
@startuml Interface Builder class MargaritaBuilder class CreamyBaconBuilder class Pizza note left: 每一個builder會建立本身的Pizza樣式,而Pizza定義的內容不多 class Waiter note left: waiter負責按照必定的執行順序依次執行具體的builder中的步驟,產生一個pizza Waiter #-- Builder Builder <|-- MargaritaBuilder Builder <|-- CreamyBaconBuilder MargaritaBuilder ..> Pizza CreamyBaconBuilder ..> Pizza @enduml
代碼樣例來自《精通 python 設計模式》python
# coding: utf-8 from enum import Enum import time # 定義執行過程和Pizza口味的打印信息 PizzaProgress = Enum('PizzaProgress', 'queued preparation baking ready') PizzaDough = Enum('PizzaDough', 'thin thick') PizzaSauce = Enum('PizzaSauce', 'tomato creme_fraiche') PizzaTopping = Enum('PizzaTopping', 'mozzarella double_mozzarella bacon ham mushrooms red_onion oregano') STEP_DELAY = 3 # 考慮是示例,單位爲秒 class Pizza: # 要建立的產品,pizza,包含幾個部分dough、sauce、topping def __init__(self, name): self.name = name self.dough = None self.sauce = None self.topping = [] def __str__(self): return self.name # 此段代碼也能夠在builder中實現,目的是爲了展現不單單是能夠定義Pizza屬性,也能夠定義一些方法, # 來讓builder調用 def prepare_dough(self, dough): self.dough = dough print('preparing the {} dough of your {}...'.format(self.dough.name, self)) time.sleep(STEP_DELAY) print('done with the {} dough'.format(self.dough.name)) class MargaritaBuilder: def __init__(self): # builder類建立的margatita pizza對象 # 此處可以表現出產品的建立由builder類建立 self.pizza = Pizza('margarita') self.progress = PizzaProgress.queued self.baking_time = 5 # 考慮是示例,單位爲秒 # 以下的過程都是builder類抽象出的統一接口,全部的builder都有這些接口,因爲python與java不一樣,能夠不用提早定義抽象類來繼承 def prepare_dough(self): self.progress = PizzaProgress.preparation self.pizza.prepare_dough(PizzaDough.thin) def add_sauce(self): print('adding the tomato sauce to your margarita...') self.pizza.sauce = PizzaSauce.tomato time.sleep(STEP_DELAY) print('done with the tomato sauce') def add_topping(self): print('adding the topping (double mozzarella, oregano) to your margarita') # 此處實在topping的0位置添加了一個[]list self.pizza.topping.append([i for i in (PizzaTopping.double_mozzarella, PizzaTopping.oregano)]) time.sleep(STEP_DELAY) print('done with the topping (double mozzarrella, oregano)') def bake(self): self.progress = PizzaProgress.baking print('baking your margarita for {} seconds'.format(self.baking_time)) time.sleep(self.baking_time) self.progress = PizzaProgress.ready print('your margarita is ready') class CreamyBaconBuilder: def __init__(self): self.pizza = Pizza('creamy bacon') self.progress = PizzaProgress.queued self.baking_time = 7 # 考慮是示例,單位爲秒 def prepare_dough(self): self.progress = PizzaProgress.preparation self.pizza.prepare_dough(PizzaDough.thick) def add_sauce(self): print('adding the crème fraîche sauce to your creamy bacon') self.pizza.sauce = PizzaSauce.creme_fraiche time.sleep(STEP_DELAY) print('done with the crème fraîche sauce') def add_topping(self): print('adding the topping (mozzarella, bacon, ham, mushrooms, red onion, oregano) to your creamy bacon') self.pizza.topping.append([t for t in (PizzaTopping.mozzarella, PizzaTopping.bacon, PizzaTopping.ham, PizzaTopping.mushrooms, PizzaTopping.red_onion, PizzaTopping.oregano)]) time.sleep(STEP_DELAY) print('done with the topping (mozzarella, bacon, ham, mushrooms, red onion, oregano)') def bake(self): self.progress = PizzaProgress.baking print('baking your creamy bacon for {} seconds'.format(self.baking_time)) time.sleep(self.baking_time) self.progress = PizzaProgress.ready print('your creamy bacon is ready') # waiter做爲一個director定義了執行過程 class Waiter: def __init__(self): self.builder = None def construct_pizza(self, builder): self.builder = builder # step by step一步一步的執行pizza的製做過程 [step() for step in (builder.prepare_dough, builder.add_sauce, builder.add_topping, builder.bake)] @property def pizza(self): return self.builder.pizza def validate_style(builders): try: pizza_style = input('What pizza would you like, [m]argarita or [c]reamy bacon? ') builder = builders[pizza_style]() # 根據用戶輸入產生builder valid_input = True except KeyError as err: print('Sorry, only margarita (key m) and creamy bacon (key c) are available') return (False, None) return (True, builder) def main(): builders = dict(m=MargaritaBuilder, c=CreamyBaconBuilder) valid_input = False while not valid_input: valid_input, builder = validate_style(builders) print() waiter = Waiter() waiter.construct_pizza(builder) pizza = waiter.pizza print() print('Enjoy your {}!'.format(pizza)) if __name__ == '__main__': main()
[step() for step in (builder.prepare_dough, builder.add_sauce, builder.add_topping, builder.bake)]