####零、建造者模式
- 什么是建造者模式
使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于建造者模式,它提供了一种创建对象的最佳方式,将一个复杂对象的构造过程与其表象分离,同一个构造过程可用于创建多个不同的表现。
####一、身边的例子
- 麦当劳
麦当劳的汉堡套餐种类有很多(如:汉堡+可乐、汉堡+薯条、汉堡+可乐+薯条),顾客在购买的时候关注的是套餐的种类(表现),而不关注套餐制作的过程(建造过程)。在这里顾客就是客户端,收银员就是指挥者,后厨人员就是建造者。
- django-widgy
django-widgy是Django的第三方编辑器扩展,可以构建不同风格的HTML代码。
####二、什么情况下使用
创建一个由多个部分构成的对象,而且它的构成需要一步接一步地完成,只有当各个部分都创建好后,这个对象才算创建完成。
####三、应用案例
以下代码,通过订购两种不同口味的比萨并,来进一步学习建造者模式
import time from enum import Enum 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: ''' 最终产品类 ''' def __init__(self, name): self.name = name self.dough = None self.sauce = None self.topping = [] def __str__(self): return self.name def prepare_dough(self, dough): self.dough = dough print('preparing the {} dough of you {}...'.format(self.dough.name, self)) time.sleep(STEP_DELAY) print('done with the {} dough'.format(self.dough.name)) 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.thin) # 添加沙司 def add_sauce(self): print('adding the creme fraiche sauce to your creamy bacon') self.pizza.sauce = PizzaSauce.Creme_fraiche # 暂停3秒,模拟制作的时间 time.sleep(STEP_DELAY) print('done with the creme fraiche 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') class MargaritaBuilder: ''' 玛格丽特比萨建造者 ''' def __init__(self): self.pizza = Pizza('margarita') self.progress = PizzaProgress.queued self.baking_time = 5 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') 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 Waiter: ''' 服务员(指挥者) ''' def __init__(self): self.builder = None def construct_pizza(self, builder): self.builder = builder [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]() vaild_input = True except KeyError as err: print('Sorry,only margarita (key m) and creamy bacon (key c) are availabke') 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) waiter = Waiter() waiter.construct_pizza(builder) pizza = waiter.pizza print('Enjoy your {}!'.format(pizza)) if __name__ == '__main__': main()