Python 设计模式

编程入门 行业动态 更新时间:2024-10-28 20:16:35

Python 设计<a href=https://www.elefans.com/category/jswz/34/1771241.html style=模式"/>

Python 设计模式

精通Python设计模式第二版 第 2 章 建造者模式 学习笔记

建造者模式

假设我们要创建一个由对各部分组成的独享,而且创建过程需要一步一步地完成。只有创建了所有的部分,该对象才是完成的。这种需求可以使用建造者模式帮助我们。建造者模式将复杂对象的构建与其表示分离。通过将构建与表示分离,相同的构建可用于创建几个不同的表示

假设我们想创建一个HTML页面生成器。HTML页面的基础结构(构建部分)大同小异:以<html>开始,以</html>结束,在HTML部分中有<head></head>元素,在head部分中有<title>和</title>原色,以此类推。但是页面的表示可能不同。每个页面都有自己的标题、头部和不同的<body>内容。此外,页面通常按步骤构建:一个函数添加标题,一个函数添加主头部,一个函数添加脚注,等等。只有在页面的整个结构完成之后,才能使用一个最终的渲染函数将其呈现给客户端。我们可以进一步拓展HTML生成器,使其能够生成完全不同的HTML页面。一个页面可能包含表格,一个可能包含图像库,一个页面可能包含联系人表单,等等

两个参与者

  • 建造者(builder):负责创建复杂独享的各个部分的组件。
  • 指挥者(director):使用建造者实例控制构建过程的组件。

定制个人计算机问题

假设我们想买一台新计算机,计算机的配置我们自己挑选。我们可以使用建造者模式解决这个问题,在这个方案里,我们就是指挥者,向制造商(builder)发出指令

1. 定义Computer类

class Computer():"""Computer :Attributes:"""def __init__(self, serial_number):self.serial = serial_numberself.memory = None  # 单位为GBself.hdd = None  # 单位为GBself.gpu = Nonedef __str__(self):info = (f'Memory: {self.memory}GB',f'Hard Disk: {self.hdd}GB',f'Graphics Card: {self.gpu}')return '\n'.join(info)

2. 定义ComputerBuilder类

class Computer():"""Computer :Attributes:"""def __init__(self, serial_number):self.serial = serial_numberself.memory = None  # 单位为GBself.hdd = None  # 单位为GBself.gpu = Nonedef __str__(self):info = (f'Memory: {self.memory}GB',f'Hard Disk: {self.hdd}GB',f'Graphics Card: {self.gpu}')return '\n'.join(info)

3. 定义HardwareEngineer类

class HardwareEngineer():"""HardwareEngineer :Attributes:"""def __init__(self):self.builder = Nonedef construct_computer(self, memory, hdd, gpu):self.builder = ComputerBuilder()(self.builder.configure_memory(memory),self.builder.configure_hdd(hdd),self.builder.configure_gpu(gpu))@propertydef computer(self):return self.builder.computer

4. 以main()函数结束,并从命令行调用方法

def main():engineer = HardwareEngineer()engineer.construct_computer(hdd=500,memory=8,gpu='GeForce GTX 650 Ti')computer = engineer.computerprint(computer)if __name__ == '__main__':main()

获得打印如下

Memory: 8GB
Hard Disk: 500GB
Graphics Card: GeForce GTX 650 Ti

完整代码如下


class Computer():"""Computer :Attributes:"""def __init__(self, serial_number):self.serial = serial_numberself.memory = None  # 单位为GBself.hdd = None  # 单位为GBself.gpu = Nonedef __str__(self):info = (f'Memory: {self.memory}GB',f'Hard Disk: {self.hdd}GB',f'Graphics Card: {self.gpu}')return '\n'.join(info)class ComputerBuilder():"""ComputerBuilder :Attributes:"""def __init__(self):self.computer = Computer('AG23385193')def configure_memory(self, amount):self.computer.memory = amountdef configure_hdd(self, amount):self.computer.hdd = amountdef configure_gpu(self, gpu_model):self.computer.gpu = gpu_modelclass HardwareEngineer():"""HardwareEngineer :Attributes:"""def __init__(self):self.builder = Nonedef construct_computer(self, memory, hdd, gpu):self.builder = ComputerBuilder()(self.builder.configure_memory(memory),self.builder.configure_hdd(hdd),self.builder.configure_gpu(gpu))@propertydef computer(self):return self.builder.computerdef main():engineer = HardwareEngineer()engineer.construct_computer(hdd=500,memory=8,gpu='GeForce GTX 650 Ti')computer = engineer.computerprint(computer)if __name__ == '__main__':main()

这个方案中,我们引入了建造者CompuerBuilder、指挥者HardwareEngineer,并逐步构建了一台计算机,它现在支持不同的配置memory,hdd,gpu

定制披萨问题

现在让我们看看如果使用建造者设计模式来制作比萨订购程序。披萨的例子特别又去,因为披萨的制作不走应该遵循特定的顺序。加调味汁之前,首先要准备面团。加配料之前,首先要加调味汁。只有调味汁和配料都放在面团上后,你才能开始烤披萨。此外,每个披萨通常需要不同的烘烤时间,这取决于面团的厚度和所用的配料

1. 声明一些Enum

使用这些枚举来记录制作披萨的状态以及披萨的一些相关属性

from enum import Enum
import timePizzaProgress = 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  # 单位为秒

2. 定义Pizza类

class Pizza():"""Pizza :Attributes:"""def __init__(self, name):self.name = nameself.dough = Noneself.sauce = Noneself.topping = []def __str__(self):return self.namedef prepare_dough(self, dough):self.dough = doughprint(f'preparing the {self.dough.name} dough of your {self}...')time.sleep(STEP_DELAY)print(f'done with the {self.dough.name} dough')

3. 定义Builder类

有两个建造者:一个用于创建玛格丽特披萨,另一个用于创建奶油培根披萨。每个建造者创建一个Pizza实例,并包含遵循比萨制作过程的方法:prepare_dough()、add_sauce() 等。

class MargaritaBuilder():"""MargaritaBuilder :Attributes:"""def __init__(self):self.pizza = Pizza('margarita')self.progress = PizzaProgress.queuedself.baking_time = 5  # 单位为秒,仅做示例使用def prepare_dough(self):self.progress = PizzaProgress.preparationself.pizza.prepare_dough(PizzaDough.thin)def add_sauce(self):print('adding the tomato sauce to your margarita')self.pizza.sauce = PizzaSauce.tomatotime.sleep(STEP_DELAY)print('done with the tomato sauce')def add_topping(self):topping_desc = 'double mozzarella, oregano'topping_items = (PizzaTopping.double_mozzarella, PizzaTopping.oregano)print(f'adding the topping ({topping_desc}) to your margarita')self.pizza.topping.append([t for t in topping_items])time.sleep(STEP_DELAY)print(f'done with the topping ({topping_desc})')def bake(self):self.progress = PizzaProgress.bakingprint(f'baking your margarita for {self.baking_time} seconds')time.sleep(self.baking_time)self.progress = PizzaProgress.readyprint('your margarita is ready')class CreamyBaconBuilder():"""CreamyBaconBuilder :Attributes:"""def __int__(self):self.pizza = Pizza('creamy bacon')self.progress = PizzaProgress.queuedself.baking_time = 7  # 单位为秒def prepare_dough(self):self.progress = PizzaProgress.preparationself.pizza.prepare_dough(PizzaDough.thick)def add_sauce(self):print('adding the creme fraiche sauce to your creamy bacon')self.pizza.sauce = PizzaSauce.creme_fraichetime.sleep(STEP_DELAY)print('done with the creme fraiche sauce')def add_topping(self):topping_desc = 'mozzarella, bacon, ham, mushrooms, red onion, oregano'topping_items = (PizzaTopping.mozzarella,PizzaTopping.bacon,PizzaTopping.ham,PizzaTopping.mushrooms,PizzaTopping.red_onion,PizzaTopping.oregano)print(f'adding the topping ({topping_desc}) to your creamy bacon')self.pizza.topping.append([t for t in topping_items])time.sleep(STEP_DELAY)print(f'done with the topping ({topping_desc})')def bake(self):self.progress = PizzaProgress.bakingprint(f'baking your creamy bacon for {self.baking_time} seconds')time.sleep(self.baking_time)self.progress = PizzaProgress.readyprint('your creamy bacon is ready')

4. 定义Waiter类

在这个例子中 指挥者是服务员。Waiter类的核心是construct_pizza()方法,它接收一个建造者作为参数,并以正确的顺序执行所有比萨准备。

class Waiter():"""Waiter :Attributes:"""def __init__(self):self.builder = Nonedef construct_pizza(self, builder):self.builder = buildersteps = (builder.prepare_dough,builder.add_sauce,builder.add_topping,builder.bake)[step() for step in steps]@propertydef pizza(self):return self.builder.pizza

5. 处理订单需求

validate_style() 确保用户提供有效的输入

def validate_style(builders):try:input_msg = 'What pizza would you like, [m]argarita or [c]reamy bacon? \n'pizza_style = input(input_msg)builder = builders[pizza_style]()valid_input = Trueexcept KeyError:error_msg = 'Sorry, only margarita (key m) and creamy bacon (key c) are available'print(error_msg)return (False, None)return (True, builder)def main():builders = dict(m=MargaritaBuilder, c=CreamyBaconBuilder)valid_input = Falsewhile not valid_input:valid_input, builder = validate_style(builders)print()waiter = Waiter()waiter.construct_pizza(builder)pizza = waiter.pizzaprint()print(f'Enjoy your {pizza}!')if __name__ == '__main__':main()

获得打印如下

What pizza would you like, [m]argarita or [c]reamy bacon? 
mpreparing the thin dough of your margarita...
done with the thin dough
adding the tomato sauce to your margarita
done with the tomato sauce
adding the topping (double mozzarella, oregano) to your margarita
done with the topping (double mozzarella, oregano)
baking your margarita for 5 seconds
your margarita is readyEnjoy your margarita!

完整代码如下


from enum import Enum
import timePizzaProgress = 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 :Attributes:"""def __init__(self, name):self.name = nameself.dough = Noneself.sauce = Noneself.topping = []def __str__(self):return self.namedef prepare_dough(self, dough):self.dough = doughprint(f'preparing the {self.dough.name} dough of your {self}...')time.sleep(STEP_DELAY)print(f'done with the {self.dough.name} dough')class MargaritaBuilder():"""MargaritaBuilder :Attributes:"""def __init__(self):self.pizza = Pizza('margarita')self.progress = PizzaProgress.queuedself.baking_time = 5  # 单位为秒,仅做示例使用def prepare_dough(self):self.progress = PizzaProgress.preparationself.pizza.prepare_dough(PizzaDough.thin)def add_sauce(self):print('adding the tomato sauce to your margarita')self.pizza.sauce = PizzaSauce.tomatotime.sleep(STEP_DELAY)print('done with the tomato sauce')def add_topping(self):topping_desc = 'double mozzarella, oregano'topping_items = (PizzaTopping.double_mozzarella, PizzaTopping.oregano)print(f'adding the topping ({topping_desc}) to your margarita')self.pizza.topping.append([t for t in topping_items])time.sleep(STEP_DELAY)print(f'done with the topping ({topping_desc})')def bake(self):self.progress = PizzaProgress.bakingprint(f'baking your margarita for {self.baking_time} seconds')time.sleep(self.baking_time)self.progress = PizzaProgress.readyprint('your margarita is ready')class CreamyBaconBuilder():"""CreamyBaconBuilder :Attributes:"""def __int__(self):self.pizza = Pizza('creamy bacon')self.progress = PizzaProgress.queuedself.baking_time = 7  # 单位为秒def prepare_dough(self):self.progress = PizzaProgress.preparationself.pizza.prepare_dough(PizzaDough.thick)def add_sauce(self):print('adding the creme fraiche sauce to your creamy bacon')self.pizza.sauce = PizzaSauce.creme_fraichetime.sleep(STEP_DELAY)print('done with the creme fraiche sauce')def add_topping(self):topping_desc = 'mozzarella, bacon, ham, mushrooms, red onion, oregano'topping_items = (PizzaTopping.mozzarella,PizzaTopping.bacon,PizzaTopping.ham,PizzaTopping.mushrooms,PizzaTopping.red_onion,PizzaTopping.oregano)print(f'adding the topping ({topping_desc}) to your creamy bacon')self.pizza.topping.append([t for t in topping_items])time.sleep(STEP_DELAY)print(f'done with the topping ({topping_desc})')def bake(self):self.progress = PizzaProgress.bakingprint(f'baking your creamy bacon for {self.baking_time} seconds')time.sleep(self.baking_time)self.progress = PizzaProgress.readyprint('your creamy bacon is ready')class Waiter():"""Waiter :Attributes:"""def __init__(self):self.builder = Nonedef construct_pizza(self, builder):self.builder = buildersteps = (builder.prepare_dough,builder.add_sauce,builder.add_topping,builder.bake)[step() for step in steps]@propertydef pizza(self):return self.builder.pizzadef validate_style(builders):try:input_msg = 'What pizza would you like, [m]argarita or [c]reamy bacon? \n'pizza_style = input(input_msg)builder = builders[pizza_style]()valid_input = Trueexcept KeyError:error_msg = 'Sorry, only margarita (key m) and creamy bacon (key c) are available'print(error_msg)return (False, None)return (True, builder)def main():builders = dict(m=MargaritaBuilder, c=CreamyBaconBuilder)valid_input = Falsewhile not valid_input:valid_input, builder = validate_style(builders)print()waiter = Waiter()waiter.construct_pizza(builder)pizza = waiter.pizzaprint()print(f'Enjoy your {pizza}!')if __name__ == '__main__':main()

流畅创建者

简略版建造者模型 解决披萨订单问题


class Pizza():"""Pizza :Attributes:"""def __init__(self,builder):self.garlic = builder.garlicself.extra_cheese = builder.extra_cheesedef __str__(self):garlic = 'yes' if self.garlic else 'no'cheese = 'yes' if self.extra_cheese else 'no'info = (f'Garlic: {garlic}',f'Extra cheese: {cheese}')return '\n'.join(info)class PizzaBuilder():"""PizzaBuilder :Attributes:"""def __init__(self):self.extra_cheese = Falseself.garlic = Falsedef add_garlic(self):self.garlic = Truereturn selfdef add_cheese(self):self.extra_cheese = Truereturn selfdef build(self):return Pizza(self)if __name__ == '__main__':pizza = Pizza.PizzaBuilder().add_cheese().add_garlic().build()print(pizza)

获得打印如下

Garlic: yes
Extra cheese: yes

更多推荐

Python 设计模式

本文发布于:2023-07-02 20:41:44,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/996222.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模式   Python

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!