刘刚刚的个人博客

HeadFirst 设计模式--迭代器与组合模式

创建时间:2023-02-12 22:07:50
更新时间:2023-02-12 22:07:50

迭代器可以让我们游走于集合内部,组合模式可以让我们的使用一致的方式来处理对象或者对象的组合。

迭代器与组合模式

迭代器模式

迭代器模式提供一个方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

使用迭代器模式的好处:

  1. 让我们可以游走于聚合内部的每一个元素,而又不暴露其内部的表示
  2. 把游走的任务放在迭代器上,而不是聚合上,简化了聚合的接口和实现,也让责任各得其所。
tip:

虽然for循环可以直接遍历聚合对象,但是为了演示迭代器模式,在代码中,我们使用while循环。

class MenuItem:
    name = None
    desc = None
    vegetarian = None
    price = None

    def __init__(self, name, desc, vegetarian, price):
        self.name = name
        self.desc = desc
        self.vegetarian = vegetarian
        self.price = price


from abc import ABC, abstractmethod


class Iterator(ABC):
    @abstractmethod
    def has_next(self):
        pass

    @abstractmethod
    def next(self):
        pass


class Menu(ABC):

    @abstractmethod
    def create_iterator(self):
        pass


class DinerMenuIterator(Iterator):
    menus = None
    position = 0

    def __init__(self, menus):
        self.menus = menus

    def next(self):
        res = self.menus[self.position]
        self.position += 1
        return res

    def has_next(self):
        if self.position >= len(self.menus):
            return False
        else:
            return True


class DinerMenu(Menu):
    menus = []

    def add_menu_item(self, item):
        self.menus.append(item)

    def create_iterator(self):
        return DinerMenuIterator(self.menus)


class Waitress:
    menu = None

    def __init__(self, menus):
        self.menus = menus

    def print_menus(self):
        menu_iter = self.menus.create_iterator
        self.print_menus_func(menu_iter)

    def print_menus_func(self, iterator):
        while iterator.has_next():
            print(iterator.next())

在代码中,Waitress通过使用菜单的迭代器,来实现了菜单的遍历。

组合模式

组合模式允许将对象组合成树形结构来表现“整体/部分”的层次结构。组合可以让客户以一致的方式处理个别对象及对象组合。

组合模式的好处:

  1. 允许客户对个别对象以及组合对象一视同仁
  2. 组合结构内的任意对象成为组件,组件可以是组件也可以是叶节点
from abc import ABC, abstractmethod


class MenuComponent(ABC):

    def add(self, menu_component):
        raise NotImplementedError

    def remove(self, menu_component):
        raise NotImplementedError

    def get_child(self, i):
        raise NotImplementedError

    def get_name(self):
        raise NotImplementedError

    def get_description(self):
        raise NotImplementedError

    def get_price(self):
        raise NotImplementedError

    def is_vegetarian(self):
        raise NotImplementedError

    def print(self):
        raise NotImplementedError


class MenuItem(MenuComponent):
    name = None
    description = None
    vegetarian = None
    price = None

    def __init__(self, name, description, vegetarian, price):
        self.name = name
        self.description = description
        self.vegetarian = vegetarian
        self.price = price

    def get_name(self):
        return self.name

    def get_description(self):
        return self.description

    def get_price(self):
        return self.price

    def is_vegetarian(self):
        return self.vegetarian

    def print(self):
        msg = f"  {self.get_name()}{'(v)' if self.is_vegetarian() else ''},{self.get_price()}  --{self.get_description()}"
        print(msg)


class Menu(MenuComponent):
    menuComponents = []
    name = None
    description = None

    def __init__(self, name, description):
        self.name = name
        self.description = description

    def add(self, menu_item):
        self.menuComponents.append(menu_item)

    def remove(self, menu_item):
        self.menuComponents.remove(menu_item)

    def get_child(self, i):
        return self.menuComponents[i]

    def get_name(self):
        return self.name

    def get_description(self):
        return self.description

    def print(self):
        print(f'''\n {self.get_name()}
        {self.get_description()}
        ------------------------
        ''')

        # 书中使用的是has_next()与while配合,但Python的迭代器中没有has_next()
        # 所以此处使用while循环
        for i in self.menuComponents:
            i.print()


class Waitress:
    all_menus = None

    def __init__(self, all_menus):
        self.all_menus = all_menus

    def print_menus(self):
        print(self.all_menus)

在此处代码中,菜单和菜单项有相同的父类,同时将迭代及输出的任务放到了菜单中。

组合迭代器

使用组合迭代器,可以使用统一的方法处理组合模式中的组件(叶子和节点)。

from abc import ABC, abstractmethod


class MenuComponent(ABC):

    def add(self, menu_component):
        raise NotImplementedError

    def remove(self, menu_component):
        raise NotImplementedError

    def get_child(self, i):
        raise NotImplementedError

    def get_name(self):
        raise NotImplementedError

    def get_description(self):
        raise NotImplementedError

    def get_price(self):
        raise NotImplementedError

    def is_vegetarian(self):
        raise NotImplementedError

    def print_(self):
        raise NotImplementedError

    def create_iterator(self):
        raise Exception


class Iterator(ABC):
    @abstractmethod
    def has_next(self):
        pass

    @abstractmethod
    def next(self):
        pass


class NullIterator(Iterator):
    def next(self):
        return None

    def has_next(self):
        return False


class CompositeIterator(Iterator):
    stack = []

    def __init__(self, iterator):
        self.stack.append(iterator)

    def next(self):
        if not self.has_next():
            return None

        iterator = self.stack[-1]
        component = iterator.next()
        if isinstance(component, Menu):
            self.stack.append(component.create_iterator())
        return component

    def has_next(self):
        # 检查堆栈是否被清空
        if not self.stack:
            return False
        # 递归检查下一个元素是否有值
        iterator = self.stack[-1]
        if not iterator.has_next():
            # 当下一个元素为空时,将其弹出
            self.stack.pop()
        else:
            return True


class MenuItem(MenuComponent):
    name = None
    description = None
    vegetarian = None
    price = None

    def __init__(self, name, description, vegetarian, price):
        self.name = name
        self.description = description
        self.vegetarian = vegetarian
        self.price = price

    def get_name(self):
        return self.name

    def get_description(self):
        return self.description

    def get_price(self):
        return self.price

    def is_vegetarian(self):
        return self.vegetarian

    def print_(self):
        msg = f"  {self.get_name()}{'(v)' if self.is_vegetarian() else ''},{self.get_price()}  --{self.get_description()}"
        print(msg)

    def create_iterator(self):
        return NullIterator()


class Menu(MenuComponent):
    menuComponents = []
    name = None
    description = None

    def __init__(self, name, description):
        self.name = name
        self.description = description

    def add(self, menu_item):
        self.menuComponents.append(menu_item)

    def remove(self, menu_item):
        self.menuComponents.remove(menu_item)

    def get_child(self, i):
        return self.menuComponents[i]

    def get_name(self):
        return self.name

    def get_description(self):
        return self.description

    def print_(self):
        print(f'''\n {self.get_name()}
        {self.get_description()}
        ------------------------
        ''')

        # 书中使用的是has_next()与while配合,但Python的迭代器中没有has_next()
        # 所以此处使用while循环
        for i in self.menuComponents:
            i.print()

    def create_iterator(self):
        return CompositeIterator(self.menuComponents.__iter__())


class Waitress:
    all_menus = None

    def __init__(self, all_menus):
        self.all_menus = all_menus

    def print_menus(self):
        self.all_menus.print_()

    def print_vegetarian_menu(self):
        iterator = self.all_menus.create_iterator()
        print("\nVEGETARIAN MENU\n----")
        while (iterator.has_next()):
            menu_component = iterator.next()
            try:
                if menu_component.is_vegetarian():
                    menu_component.print_()
            except Exception as e:
                ...
我的名片

昵称:shuta

职业:后台开发(python、php)

邮箱:648949076@qq.com

站点信息

建站时间: 2020/2/19
网站程序: ANTD PRO VUE + TP6.0
晋ICP备18007778号