建造者模式

浏览 449

课文

### 情景 你是一名赛百味门店的员工,每天主要的工作就是将三明治的食材:面包、肉、酱料分别准备好,等待顾客指定将其包装成一个完整的三明治。准备食材的代码模拟如下: ```python # 假设组成三明治的三种食材中种类如下: class WholeWheatBread: def __init__(self): self.name = '全麦面包' self.price = 5.0 class ChickenBreast: def __init__(self): self.name = '鸡胸肉' self.price = 10.0 class BlackPepperSauce: def __init__(self): self.name = '黑椒酱' self.price = 1.0 bread = WholeWheatBread() meat = BlackPepperSauce() sauce = BlackPepperSauce() ``` 食材已经准备好了,接下来开始组装三明治,下面记作**代码 Ⅰ**: ```python # 初始化三明治时需要分别传入面包类、肉类以及酱料类 class Sandwich: def __init__(self, bread, meat, sauce): self.bread = bread.name self.meat = meat.name self.sauce = sauce.name # 提供获取三明治组成与总价的函数 def getItems(self): print("面包: " + self.bread) print("肉: " + self.meat) print("酱料: " + self.sauce) def getCost(self): cost = self.bread.price + self.meat.price + self.sauce.price print("花费:¥", cost) sandwich = Sandwich(bread, meat, sauce) sandwich.getItems() ``` 输出: ```output 面包:全麦面包 肉:鸡胸肉 酱料:黑椒酱 花费:¥16 ``` 我们把上面的代码改造一下,记作**代码 Ⅱ**: ```python # 提供一个三明治的建造类,其中分别提供了面包、肉和酱料的添加方法 class SandwichBuilder: def order_bread(self, bread): self.bread = bread def order_meat(self, meat): self.meat = meat def order_sauce(self, sauce): self.sauce = sauce # 最后将所有的组分作为参数传进Sandwich类里 def build(self): return Sandwich(self) # 改造一下Sandwich类,让它只接受一个参数sandwich_builder class Sandwich: def __init__(self, sandwich_builder): self.bread = sandwich_builder.bread.name self.meat = sandwich_builder.meat.name self.sauce = sandwich_builder.sauce.name # 准备好食材 bread = WholeWheatBread() meat = BlackPepperSauce() sauce = BlackPepperSauce() # 实例化建造者,并调用建造者的方法添加食材 builder = SandwichBuilder() builder.order_bread(bread) builder.order_meat(meat) builder.order_sauce(sauce) # 最后调用建造者的build方法,返回一个Sandwich类的实例 sandwich = builder.build() sandwich.getItems() ``` 跟上面一样的输出: ```output 面包:全麦面包 肉:鸡胸肉 酱料:黑椒酱 花费:¥16 ``` 这种写法,就是典型的**建造者模式(Builder Pattern)**。 ### 正文 建造者模式的定义是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。它通常由几部分构成: - 产品类(Sandwich 类等) - 建造类(SandwichBuilder 类) - 指挥类(下面会细说) 用上面的例子来解释一下这个定义:「复杂对象的构建」是指 SandwichBuilder 类里的`order_xxx()`等方法,而「复杂对象的表示」则是指 SandwichBuilder 类里的`build()`方法。那么后半句怎么理解呢?回到上面代码,如果增加其中一种食材: ```python # 假设酱料里有个番茄酱 class Ketchup: def __init__(self): self.name = '番茄酱' self.price = 0.5 ``` 那么我想要一个加番茄酱的三明治,只需要仿照代码 Ⅱ 的步骤,将`BlackPepperSauce()`换成`Ketchup()`即可: ```python sauce = Ketchup() ``` 输出则会变成: ```output 面包:全麦面包 肉:鸡胸肉 酱料:番茄酱 花费:¥15.5 ``` 同样的构建过程(面包夹肉加酱料),换了组成部分的类型(将黑椒酱换成番茄酱)之后就变成了不同的表示(不一样的三明治),这就达到了用少量代码大大扩展了复杂对象的种类数量的目的。 这时候可能有人要问了:那代码 Ⅰ 不是比代码 Ⅱ 更少吗?为什么还要多余写一个 Builder 类呢? 如果能想到这一层,说明你确实是一个爱思考的开发者。跟工厂类模式一样,实际的业务场景中可能会具有较为复杂的逻辑判断过程,如果全部写在类初始化函数里,会导致代码过于臃肿,难以维护和扩展: ```python # 代码Ⅰ修改 class Sandwich: def __init__(self, bread, meat, sauce): # 假设三样东西都得有 if not bread.name or not meat.name or not sauce.name: print('住手,这根本不是三明治!') # 假设黑椒酱只能配牛排,不然会报错 elif sauce.name == '黑椒酱' and meat.name != '牛排': print('对不起,我们这边规定黑椒酱必须配牛排哦') elif ... ``` ```python # 代码Ⅱ修改 class SandwichBuilder: def order_bread(self, bread): self.bread = bread def order_meat(self, meat): self.meat = meat def order_sauce(self, sauce): if sauce.name == '黑椒酱' and self.meat.name != '牛排': print('对不起,我们这边规定黑椒酱必须配牛排哦') else: self.sauce = sauce def build(self): if not bread.name or not meat.name or not sauce.name: print('住手,这根本不是三明治!') else: return Sandwich(self) ``` 这样就能保证在业务场景变更时,修改的代码的影响范围尽可能小。 ### 什么是指挥类? (待更新)

评论

登录参与讨论

暂无评论

共 0 条
  • 1
前往
  • 1