python实现建造者模式
前言
无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮、方向盘、发送机等各种部件。而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单独某个部件,而是使用一辆完整的汽车,可以通过建造者模式对其进行设计与描述, 建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节 .
介绍
建造者模式( Builder Pattern ) 又名生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。
建造者模式 是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。
主要解决: 主要解决在软件系统中,有时候面临着 "一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用: 一些基本部件不会变,而其组合经常变化的时候。
如何解决: 将变与不变分离开。
关键代码: 建造者:创建和提供实例, 指挥者 :管理建造出来的实例的依赖关系。
应用实例: 去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。
优点: 1、建造者独立,易扩展。 2、便于控制细节风险。
缺点: 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。
使用场景: 1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。
注意事项: 与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
实例:KFC套餐
建造者模式可以用于描述KFC如何创建套餐:套餐是一个复杂对象,它一般包含主食(如汉堡、鸡肉卷等)和饮料(如果汁、可乐等)等组成部分,不同的套餐有不同的组成部分,而KFC的服务员可以根据顾客的要求,一步一步装配这些组成部分,构造一份完整的套餐,然后返回给顾客。
# 具体产品对象 class Menu: Menu_A = [] Menu_B = [] def set_MenuA(self,item): self.Menu_A.append(item) def set_MenuB(self,item): self.Menu_B.append(item) def get_MenuA(self): return self.Menu_A def get_MenuB(self): return self.Menu_B # Builder(抽象建造者) # 创建一个Product对象的各个部件指定的抽象接口。 class Product: product = Menu() def build_hanbao(self): pass def build_jiroujuan(self): pass def build_kele(self): pass def build_shutiao(self): pass # ConcreteBuilder(具体建造者) # 实现抽象接口,构建和装配各个部件。 # 套餐A class product_A(Product): type = " A " def build_hanbao(self): self.hanbao = " 汉堡 " self.product.set_MenuA(self.hanbao) def build_kele(self): self.kele = " 可乐 " self.product.set_MenuA(self.kele) def getType(self): return type # 套餐B class product_B(Product): type = " B " def build_shutiao(self): self.shutiao = " 薯条 " self.product.set_MenuB(self.shutiao) def build_jiroujuan(self): self.jiroujuan = " 鸡肉卷 " self.product.set_MenuB(self.jiroujuan) def build_kele(self): self.kele = " 可乐 " self.product.set_MenuB(self.kele) def getType(self): return type # Director(指挥者)
class Make: def __init__ (self): self.builder = None def build_product(self, builder): self.builder = builder print (builder.type) if builder.type == " A " : [step() for step in (builder.build_hanbao, builder.build_kele)] if builder.type == " B " : [step() for step in (builder.build_shutiao, builder.build_jiroujuan, builder.build_kele)] # 不同类型选择 def validate_style(builders): global valid_input try : print ( ' 套餐A:汉堡、可乐 ' + ' \n ' ' 套装B:薯条、鸡肉卷、可乐 ' ) product_style = input( ' 请输入您的选择: ' ) builder = builders[product_style]() valid_input = True except KeyError as err: print ( ' Sorry, 没有这个套餐,请重新选择。 ' ) return (False, None) return (True, builder,product_style) # 主函数 def main(): builders = dict(A=product_A, B= product_B) valid_input = False while not valid_input: valid_input, builder,product_style = validate_style(builders) Waiter = Make() Waiter.build_product(builder) if product_style == " A " : print (builder.product.get_MenuA()) else : print (builder.product.get_MenuB()) if __name__ == " __main__ " : main()
输出
套餐A:汉堡、可乐 套装B:薯条、鸡肉卷、可乐 请输入您的选择:A A [ ' 汉堡 ' , ' 可乐 ' ]