当前位置: 首页 > news >正文

基于Python学习《Head First设计模式》第九章 迭代器和组合模式

迭代器

迭代器的定义

在这里插入图片描述

类图

在这里插入图片描述

完整代码

from abc import ABC, abstractmethod
from typing import List, Optional# 菜单项类
class MenuItem:def __init__(self, name: str, description: str, vegetarian: bool, price: float):self.name = nameself.description = descriptionself.vegetarian = vegetarianself.price = pricedef __str__(self) -> str:veg_str = " [素食]" if self.vegetarian else ""return f"{self.name}{self.price:.2f}) - {self.description}{veg_str}"# 迭代器接口
class Iterator(ABC):@abstractmethoddef has_next(self) -> bool:pass@abstractmethoddef next(self) -> MenuItem:pass# 煎饼屋菜单 (使用列表)
class PancakeHouseMenu:def __init__(self):self.menu_items: List[MenuItem] = []self.add_item("传统煎饼", "配鸡蛋和吐司", True, 12.99)self.add_item("蓝莓煎饼", "新鲜蓝莓制作", True, 14.49)self.add_item("华夫饼", "配蓝莓或草莓", True, 15.59)def add_item(self, name: str, description: str,vegetarian: bool, price: float) -> None:self.menu_items.append(MenuItem(name, description, vegetarian, price))def create_iterator(self) -> Iterator:return PancakeHouseMenuIterator(self.menu_items)# 煎饼屋菜单迭代器
class PancakeHouseMenuIterator(Iterator):def __init__(self, items: List[MenuItem]):self.items = itemsself.position = 0def has_next(self) -> bool:return self.position < len(self.items)def next(self) -> MenuItem:item = self.items[self.position]self.position += 1return item# 餐厅菜单 (使用固定大小数组)
class DinerMenu:MAX_ITEMS = 6def __init__(self):self.menu_items: List[Optional[MenuItem]] = [None] * self.MAX_ITEMSself.number_of_items = 0self.add_item("蔬菜汤", "时令蔬菜汤", True, 13.29)self.add_item("热狗", "酸菜配黄芥末", False, 13.05)self.add_item("烤鸡", "土豆泥配蔬菜", False, 30.99)def add_item(self, name: str, description: str,vegetarian: bool, price: float) -> None:if self.number_of_items >= self.MAX_ITEMS:print("错误:菜单已满!无法添加新菜品")returnself.menu_items[self.number_of_items] = MenuItem(name, description, vegetarian, price)self.number_of_items += 1def create_iterator(self) -> Iterator:return DinerMenuIterator(self.menu_items, self.number_of_items)# 餐厅菜单迭代器
class DinerMenuIterator(Iterator):def __init__(self, items: List[Optional[MenuItem]], item_count: int):self.items = itemsself.item_count = item_countself.position = 0def has_next(self) -> bool:# 跳过空位置while (self.position < self.item_count andself.items[self.position] is None):self.position += 1return self.position < self.item_countdef next(self) -> MenuItem:if not self.has_next():raise StopIteration()item = self.items[self.position]self.position += 1return item# 女招待 (客户端)
class Waitress:def __init__(self, pancake_menu: PancakeHouseMenu, diner_menu: DinerMenu):self.pancake_menu = pancake_menuself.diner_menu = diner_menudef print_menu(self) -> None:print("====== 早餐菜单 ======")self._print_menu(self.pancake_menu.create_iterator())print("\n====== 午餐菜单 ======")self._print_menu(self.diner_menu.create_iterator())def _print_menu(self, iterator: Iterator) -> None:while iterator.has_next():menu_item = iterator.next()print(menu_item)# 测试代码
if __name__ == "__main__":pancake_menu = PancakeHouseMenu()diner_menu = DinerMenu()waitress = Waitress(pancake_menu, diner_menu)waitress.print_menu()"""运行结果:
====== 早餐菜单 ======
传统煎饼 (¥12.99) - 配鸡蛋和吐司 [素食]
蓝莓煎饼 (¥14.49) - 新鲜蓝莓制作 [素食]
华夫饼 (¥15.59) - 配蓝莓或草莓 [素食]====== 午餐菜单 ======
蔬菜汤 (¥13.29) - 时令蔬菜汤 [素食]
热狗 (¥13.05) - 酸菜配黄芥末
烤鸡 (¥30.99) - 土豆泥配蔬菜
"""

要点

在这里插入图片描述

组合模式

组合模式的定义

在这里插入图片描述

类图

在这里插入图片描述

完整代码


from abc import ABC, abstractmethod
from typing import Listclass MenuComponent(ABC):"""菜单组件的抽象基类"""def add(self, component: 'MenuComponent') -> None:raise NotImplementedError("不支持添加操作")def remove(self, component: 'MenuComponent') -> None:raise NotImplementedError("不支持移除操作")def get_child(self, i: int) -> 'MenuComponent':raise NotImplementedError("不支持获取子项")@abstractmethoddef get_name(self) -> str:pass@abstractmethoddef get_description(self) -> str:pass@abstractmethoddef get_price(self) -> float:pass@abstractmethoddef is_vegetarian(self) -> bool:pass@abstractmethoddef print(self) -> None:passclass MenuItem(MenuComponent):"""叶子节点:菜单项"""def __init__(self, name: str, description: str,vegetarian: bool, price: float):self.name = nameself.description = descriptionself.vegetarian = vegetarianself.price = pricedef get_name(self) -> str:return self.namedef get_description(self) -> str:return self.descriptiondef get_price(self) -> float:return self.pricedef is_vegetarian(self) -> bool:return self.vegetariandef print(self) -> None:veg_str = " (素食)" if self.vegetarian else ""print(f"  {self.name}{veg_str}, ¥{self.price:.2f}")print(f"    -- {self.description}")class Menu(MenuComponent):"""组合节点:菜单(可以包含菜单项或子菜单)"""def __init__(self, name: str, description: str):self.name = nameself.description = descriptionself.components: List[MenuComponent] = []def add(self, component: MenuComponent) -> None:self.components.append(component)def remove(self, component: MenuComponent) -> None:self.components.remove(component)def get_child(self, i: int) -> MenuComponent:return self.components[i]def get_name(self) -> str:return self.namedef get_description(self) -> str:return self.descriptiondef get_price(self) -> float:raise NotImplementedError("菜单没有价格")def is_vegetarian(self) -> bool:raise NotImplementedError("菜单没有素食属性")def print(self) -> None:print(f"\n{self.name}, {self.description}")print("-" * 50)for component in self.components:component.print()class Waitress:"""女招待类 - 客户端"""def __init__(self, all_menus: MenuComponent):self.all_menus = all_menusdef print_menu(self) -> None:self.all_menus.print()def print_vegetarian_menu(self) -> None:print("\n===== 素食菜单 =====")self._print_vegetarian(self.all_menus)def _print_vegetarian(self, component: MenuComponent) -> None:try:if component.is_vegetarian():print(f"  {component.get_name()}, ¥{component.get_price():.2f}")print(f"    -- {component.get_description()}")except NotImplementedError:passtry:for child in component.components:self._print_vegetarian(child)except AttributeError:passdef build_menu_system() -> MenuComponent:"""构建整个菜单系统"""# 顶层菜单all_menus = Menu("主菜单", "所有菜单的总和")# 早餐菜单breakfast_menu = Menu("早餐菜单", "早晨供应")breakfast_menu.add(MenuItem("煎饼", "配枫糖浆", True, 12.99))breakfast_menu.add(MenuItem("华夫饼", "配蓝莓", True, 14.99))breakfast_menu.add(MenuItem("培根鸡蛋", "配吐司", False, 18.99))# 午餐菜单lunch_menu = Menu("午餐菜单", "中午供应")lunch_menu.add(MenuItem("蔬菜汤", "时令蔬菜", True, 16.99))lunch_menu.add(MenuItem("烤鸡三明治", "配沙拉", False, 22.99))lunch_menu.add(MenuItem("凯撒沙拉", "新鲜蔬菜", True, 18.99))# 晚餐菜单dinner_menu = Menu("晚餐菜单", "晚上供应")dinner_menu.add(MenuItem("牛排", "配烤土豆", False, 68.99))dinner_menu.add(MenuItem("烤三文鱼", "配蔬菜", False, 58.99))dinner_menu.add(MenuItem("素食意面", "配番茄酱", True, 36.99))# 甜点菜单(作为晚餐的子菜单)dessert_menu = Menu("甜点菜单", "餐后甜点")dessert_menu.add(MenuItem("苹果派", "配香草冰淇淋", True, 18.99))dessert_menu.add(MenuItem("巧克力蛋糕", "双层巧克力", True, 22.99))dessert_menu.add(MenuItem("奶酪拼盘", "精选奶酪", False, 28.99))# 添加到晚餐菜单dinner_menu.add(dessert_menu)# 咖啡菜单(独立菜单)cafe_menu = Menu("咖啡菜单", "全天供应")cafe_menu.add(MenuItem("浓缩咖啡", "纯正意大利风味", True, 12.99))cafe_menu.add(MenuItem("卡布奇诺", "现磨咖啡", True, 16.99))cafe_menu.add(MenuItem("热巧克力", "比利时巧克力", True, 14.99))# 将所有菜单添加到顶层菜单all_menus.add(breakfast_menu)all_menus.add(lunch_menu)all_menus.add(dinner_menu)all_menus.add(cafe_menu)return all_menusif __name__ == "__main__":# 构建菜单系统menu_system = build_menu_system()# 创建女招待waitress = Waitress(menu_system)print("=" * 50)print("餐厅完整菜单:")print("=" * 50)waitress.print_menu()print("\n" + "=" * 50)print("素食选项:")print("=" * 50)waitress.print_vegetarian_menu()"""运行结果:
==================================================
餐厅完整菜单:
==================================================主菜单, 所有菜单的总和
--------------------------------------------------早餐菜单, 早晨供应
--------------------------------------------------煎饼 (素食), ¥12.99-- 配枫糖浆华夫饼 (素食), ¥14.99-- 配蓝莓培根鸡蛋, ¥18.99-- 配吐司午餐菜单, 中午供应
--------------------------------------------------蔬菜汤 (素食), ¥16.99-- 时令蔬菜烤鸡三明治, ¥22.99-- 配沙拉凯撒沙拉 (素食), ¥18.99-- 新鲜蔬菜晚餐菜单, 晚上供应
--------------------------------------------------牛排, ¥68.99-- 配烤土豆烤三文鱼, ¥58.99-- 配蔬菜素食意面 (素食), ¥36.99-- 配番茄酱甜点菜单, 餐后甜点
--------------------------------------------------苹果派 (素食), ¥18.99-- 配香草冰淇淋巧克力蛋糕 (素食), ¥22.99-- 双层巧克力奶酪拼盘, ¥28.99-- 精选奶酪咖啡菜单, 全天供应
--------------------------------------------------浓缩咖啡 (素食), ¥12.99-- 纯正意大利风味卡布奇诺 (素食), ¥16.99-- 现磨咖啡热巧克力 (素食), ¥14.99-- 比利时巧克力==================================================
素食选项:
======================================================= 素食菜单 =====煎饼, ¥12.99-- 配枫糖浆华夫饼, ¥14.99-- 配蓝莓蔬菜汤, ¥16.99-- 时令蔬菜凯撒沙拉, ¥18.99-- 新鲜蔬菜素食意面, ¥36.99-- 配番茄酱苹果派, ¥18.99-- 配香草冰淇淋巧克力蛋糕, ¥22.99-- 双层巧克力浓缩咖啡, ¥12.99-- 纯正意大利风味卡布奇诺, ¥16.99-- 现磨咖啡热巧克力, ¥14.99-- 比利时巧克力
"""

总结

在这里插入图片描述

相关文章:

  • K8S认证|CKS题库+答案| 7. Dockerfile 检测
  • SpringCloud2025+SpringBoot3.5.0+gateway+webflux子服务路由报503
  • Linux知识回顾总结----进程状态
  • 湖北理元理律师事务所实务手记:个人债务管理的理性突围
  • Java线程工厂:定制线程的利器
  • Java八股文——并发编程「并发安全篇」
  • 基于dify的营养分析工作流:3分钟生成个人营养分析报告
  • 山东大学项目实训——基于DeepSeek的智能写作与训练平台(十二)
  • Secs/Gem第十讲(基于secs4net项目的ChatGpt介绍)
  • Python训练营打卡Day48(2025.6.8)
  • 大模型外挂MCP教程(8): 飞算JavaAI智能分析搭建自己的MCP Server
  • Σ∆ 数字滤波
  • Java设计模式面试题详解
  • 内存分配基础:修改SCT文件的简单例子
  • HBM 读的那些事
  • 网络编程(TCP编程)
  • UDP与TCP通信协议技术解析
  • GD图像处理与SESSiON
  • 禅道18.2集成LDAP
  • Linux 文件系统底层原理笔记:磁盘结构、ext2 文件系统与软硬链接解析
  • 六安招聘网/seo案例分析及解析
  • 如何建设简易网站/手机系统流畅神器
  • 淮阳住房城乡建设局网站/广西seo
  • 无上光东莞网站/太原做网站哪家好
  • 华星建设集团网站/网络营销期末考试试题及答案
  • 南阳做网站电话/大连seo网站推广