当前位置: 首页 > 后端技术 > Python

尼尔啃设计模式(0x04)建造者模式

时间:2023-03-26 18:33:19 Python

建造者模式(BuilderPattern)定义将一个复杂对象的构造与其表示分离,使得同一个构造过程可以创建不同的表示。(将一个复杂对象的构造与它的representation分离,这样同一个构造过程可以创建不同的representation。)《设计模式之禅》UML实例以创建不同口味pizza的过程为例,MargaritaPizza和CreamyBaconPizza,而Waiter作为Director,Pizza终于实现了产品化。@startumlInterfaceBuilderclassMargaritaBuilderclassCreamyBaconBuilderclassPizzanoteleft:每个builder都会创建自己的pizza样式,Pizza定义的内容非常少classWaiternoteleft:服务员负责按照一定的执行顺序执行具体builder中的步骤生成一个pizzaWaiter#--BuilderBuilder<|--MargaritaBuilderBuilder<|--CreamyBaconBuilderMargaritaBuilder..>PizzaCreamyBaconBuilder..>Pizza@endumlcodeimplementationcodesamplefrom《精通 python 设计模式》#coding:utf-8fromenumimportEnumimporttime#定义Pizza风味的执行过程和打印InformationPizzaProgress=Enum('PizzaProgress','queuedpreparationbakingready')PizzaDough=Enum('PizzaDough','thinthick')PizzaSauce=Enum('PizzaSauce','tomatocreme_fraiche')PizzaTopping=Enum('PizzaTopping','mozzarelladouble_mozzarellabaconhammushroomsred_onionoregano')STEP_DELAY=3#举个例子,单位是秒classPizza:#要创建的产品,pizza,包含面团、酱汁、浇头的几个部分def__init__(self,name):self.name=nameself.dough=Noneself.sauce=Noneself.topping=[]def__str__(self):returnself.name#这段代码也可以在builder中实现,目的是说明不仅可以定义Pizza属性,还可以定义一些方法,#让builder调用defprepare_dough(self,dough):self.dough=doughprint('准备{}面团{}...'.format(self.dough.name,self))time.sleep(STEP_DELAY)print('完成{}面团'.format(self.dough.name))classMargaritaBuilder:def__init__(self):#builder类创建的margatitapizza对象#这里可以说明product的创建是由builder类self.pizza创建的=Pizza('margarita')self.progress=PizzaProgress.queuedself.baking_time=5#以它为例,单位是秒#下面的过程是builder类抽象出来的统一接口。所有构建器都有这些接口。由于python不同于java,不需要提前定义抽象类inheritdefprepare_dough(self):self.progress=PizzaProgress.preparationself.pizza.prepare_dough(PizzaDough.thin)defadd_sauce(self):print('将番茄酱加入你的玛格丽塔酒中...')self.pizza.sauce=PizzaSauce.tomatotime.sleep(STEP_DELAY)print('donewith番茄酱')defadd_topping(self):print('在你的玛格丽塔中加入配料(双层马苏里拉奶酪、牛至)')#这里实际在配料的0位添加了一个[]listself.pizza.topping.append([iforiin(PizzaTopping.double_mozzarella,PizzaTopping.oregano)])time.sleep(STEP_DELAY)print('donewiththetopping(doublemozzarrella,oregano)')defbake(self):self.progress=PizzaProgress.baking复制代码print('将你的玛格丽塔烘焙{}秒'.format(self.baking_time))time.sleep(self.baking_time)self.progress=PizzaProgress.readyprint('你的玛格丽塔准备好了')classCreamyBaconBuilder:def__init__(self):self.pizza=Pizza('creamybacon')self.progress=PizzaProgress.queuedself.baking_time=7#思考是示范,单位为秒defprepare_dough(self):self.progress=PizzaProgress.preparationself.pizza.prepare_dough(PizzaDough.thick)defadd_sauce(self):print('在你的奶油培根中加入鲜奶油酱')self.pizza.sauce=PizzaSauce.creme_fraichetime.sleep(STEP_DELAY)print('用鲜奶油酱完成')defadd_topping(self):print('将配料(马苏里拉奶酪、培根、火腿、蘑菇、红洋葱、牛至)添加到你的奶油培根中')self.pizza.topping.append([tfortin(PizzaTopping.mozzarella,PizzaTopping.培根、PizzaTopping.ham、PizzaTopping.mushrooms、PizzaTopping.red_onion、PizzaTopping.oregano)])time.sleep(STEP_DELAY)print('完成配料(马苏里拉奶酪、培根、火腿、蘑菇、红洋葱、牛至)')defbake(self):self.progress=PizzaProgress.bakingprint('烤你的奶油培根{}秒'.format(self.baking_time))time.sleep(self.baking_time)self.progress=PizzaProgress.readyprint('yourcreamybaconisready')#waiterasadirector定义执行过程类Waiter:def__init__(self):self.builder=Nonedefconstruct_pizza(self,builder):self.builder=builder#stepbystep逐步执行披萨制作过程[step()forstepin(builder.prepare_dough,builder.add_sauce,builder.add_topping,builder.bake)]@propertydefpizza(self):returnself.builder.pizzadefvalidate_style(builders):try:pizza_style=input('Whatpizzawouldyoulike,[m]argaritaor[c]reamybacon?')builder=builders[pizza_style]()#根据用户输入生成生成器valid_input=TrueexceptKeyErroraserr:print('抱歉,只有玛格丽塔酒(keym)和奶油培根(keyc)可用')return(False,None)return(True,builder)defmain():builders=dict(m=MargaritaBuilder,c=CreamyBaconBuilder)valid_input=False而notvalid_input:valid_input,builder=validate_style(builders)print()waiter=Waiter()服务员。construct_pizza(builder)披萨=服务员。pizzaprint()print('Enjoyyour{}!'.format(pizza))if__name__=='__main__':main()ApplicationScenarioBuilder模式个人理解为定制。定制装配流程时需要使用的建造者模式和工厂模式的区别在于,工厂模式的产品有固定的规格。WriteDead,不可定制。就像买一台固定品牌和型号的电脑,或者自己组装电脑一样。前者是所有的参数都是固定的,而后者的参数则由客户来决定。如何理解建构分离?建设是创造的过程。产品应该是由多个组件组成的复杂产品。产品的构建过程有一个统一的过程,可以抽象或定义,而具体的实现则由各个构建器类实例自定义。表示是指一个产品的各种属性,而构造是指这些属性如何赋值,这些属性赋什么等等,都是由构建者构建的。所以这样做的好处是创造一个产品。product类只提供简单的属性定义,具体赋值由每个具体的builder自定义。比如上面例子中的Pizza,Pizza的属性或者非部分就是这些,不同的builder不会给不同的值。最后builder和director创建的Pizza是一个executor,根据客户的需求调用不同的builder,并将调用的action进行封装。由于构建器会提供多个执行步骤,所以不希望执行这些执行步骤。它是被用户看到的,所以它被封装了。借助导演课的知识点,学习enum的使用。编程中调用一系列函数的简化过程展示了一步一步的过程,以及封装一个过程的方式[step()forstepin(builder.prepare_dough,builder.add_sauce,builder.add_topping,builder.bake)]下一集预览模板模式