迭代器
迭代器的定义

类图

完整代码
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-- 比利时巧克力
"""
总结
