设计模式Python版 迭代器模式

文章目录


前言

GOF设计模式分三大类:

  • 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。
  • 结构型模式:关注类和对象之间的组合,包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式。
  • 行为型模式:关注对象之间的交互,包括职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。

一、迭代器模式

迭代器模式(Iterator Pattern)

  • 定义:提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(Cursor)。

  • 解决问题:如何间接遍历一个聚合对象中的元素?

  • 使用场景:

    • 访问一个聚合对象的内容而无须暴露它的内部表示。
    • 需要为一个聚合对象提供多种遍历方式。
    • 为遍历不同的聚合结构提供一个统一的接口
  • 组成:

    • Iterator(抽象迭代器):它定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法。例如first() next() has_next() current_item()
    • ConcreteIterator(具体迭代器):它实现了抽象迭代器接口,完成对聚合对象的遍历,同时在具体迭代器中通过游标来记录在聚合对象中所处的当前位置。在具体实现时,游标通常是一个表示位置的非负整数。
    • Aggregate(抽象聚合类):它用于存储和管理元素对象,声明一个createIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂角色。
    • ConcreteAggregate(具体聚合类):它实现了在抽象聚合类中声明的createIterator()方法,该方法返回一个与该具体聚合类对应的具体迭代器ConcreteIterator实例。
  • 补充说明:

    • 在软件开发中,也存在大量类似电视机一样的类,它们可以存储多个成员对象(元素),这些类通常称为聚合类(Aggregate Classes),对应的对象称为聚合对象。
    • 通过引入迭代器,客户端无须了解聚合对象的内部结构即可实现对聚合对象中成员的遍历,还可以根据需要很方便地增加新的遍历方式。
    • 迭代器模式是一种使用频率非常高的设计模式,通过引入迭代器可以将数据的遍历功能从聚合对象中分离出来。聚合对象只负责存储数据,而遍历数据由迭代器来完成。
    • 在迭代器模式结构中包含聚合和迭代器两个层次结构。考虑到系统的灵活性和可扩展性,在迭代器模式中应用了工厂方法模式
    • 在迭代器模式中应用了工厂方法模式,抽象迭代器对应于抽象产品角色,具体迭代器对应于具体产品角色,抽象聚合类对应于抽象工厂角色,具体聚合类对应于具体工厂角色。
    • 由于很多编程语言的类库都已经实现了迭代器模式,因此在实际开发中,只需要直接使用Python等语言已定义好的迭代器即可。
  • 优点:

    • 由迭代器来提供遍历聚合对象内部数据的行为,这将简化聚合对象的设计,更符合单一职责原则的要求。
    • 支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。
    • 在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足开闭原则的要求。
  • 缺点:

    • 类的个数增加,这在一定程度上增加了系统的复杂性。

二、迭代器模式示例

使用迭代器模式,设计销售管理系统中数据的遍历

  • AbstractObjectList充当抽象聚合类,ProductList充当具体聚合类,AbstractIterator充当抽象迭代器,ProductIterator充当具体迭代器。
python 复制代码
### 迭代器模式
"""抽象迭代器"""


class AbstractIterator:
    def next(self):
        # 返回下一个元素
        raise NotImplementedError

    def is_last(self) -> bool:
        # 是否为最后一个元素
        raise NotImplementedError

    def previous(self):
        # 返回上一个元素
        raise NotImplementedError

    def is_first(self):
        # 是否为第一个元素
        raise NotImplementedError


"""具体迭代器"""


class ProductIterator(AbstractIterator):
    def __init__(self, product_list: "ProductList"):
        self.product_list = product_list
        self.products = product_list.objects  # 获取集合对象
        # 正向遍历游标,配合next() is_last()方法使用
        self.cursor_f = -1
        # 逆向遍历游标,配合previous() is_first()方法使用
        self.cursor_b = len(self.products)

    def next(self):
        self.cursor_f += 1
        return self.products[self.cursor_f]

    def is_last(self):
        return self.cursor_f == len(self.products) - 1

    def previous(self):
        self.cursor_b -= 1
        return self.products[self.cursor_b]

    def is_first(self):
        return self.cursor_b == 0


"""抽象聚合类"""


class AbstractObjectList:
    def __init__(self, objects: list[object]):
        self.objects = objects

    def add_obj(self, obj: object):
        if obj not in self.objects:
            self.objects.append(obj)

    def remove_obj(self, obj: object):
        if obj in self.objects:
            self.objects.remove(obj)

    def create_iterator(self) -> AbstractIterator:
        # 创建迭代器对象的抽象工厂方法
        raise NotImplementedError


"""具体聚合类"""


class ProductList(AbstractObjectList):
    def __init__(self, objects):
        super().__init__(objects)

    def create_iterator(self):
        # 创建迭代器对象的具体工厂方法
        return ProductIterator(self)
  • 客户端代码
python 复制代码
if __name__ == "__main__":
    products = []
    products.append("《红楼梦》")
    products.append("《三国演义》")
    products.append("《水浒传》")
    products.append("《西游记》")
    products.append("《儒林外史》")

    product_list = ProductList(products)  # 创建聚合对象
    iterator = product_list.create_iterator()  # 创建迭代器对象

    print("\n正向遍历:")
    while not iterator.is_last():
        print(iterator.next(), end=" ")

    print("\n反向遍历:")
    while not iterator.is_first():
        print(iterator.previous(), end=" ")
  • 输出结果
sh 复制代码
正向遍历:
《红楼梦》 《三国演义》 《水浒传》 《西游记》 《儒林外史》 
反向遍历:
《儒林外史》 《西游记》 《水浒传》 《三国演义》 《红楼梦》

三、Python迭代器

Python迭代器

  • 在Python中,迭代器(Iterator)是一种对象,它能够被next()函数调用并返回序列中的下一个元素。直到所有元素都被迭代完毕,此时它会抛出一个StopIteration异常。
  • 迭代器协议是指对象需要实现两个方法:__iter__()__next__()
    • __iter__():返回迭代器对象本身。这意味着所有的迭代器也是可迭代的对象。
    • __next__():返回序列中的下一个元素。如果没有元素了,则抛出StopIteration异常。
  • 通常会在for循环中使用迭代器,而不是直接调用next(),因为循环结构可以自动处理StopIteration异常。for循环实际上内部使用了next()来获取每个元素,直到没有元素可以迭代。
  • Python迭代器示例:
    • 在聚合类中实现__iter__()__next__()方法
    • 然后使用for循环进行遍历
python 复制代码
class SimpleIterator:
    def __init__(self, limit):
        self.limit = limit
        self.count = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.count < self.limit:
            self.count += 1
            return self.count
        else:
            raise StopIteration


my_iterator = SimpleIterator(5)
for number in my_iterator:
    print(number)
  • 输出结果
sh 复制代码
1
2
3
4
5

您正在阅读的是《设计模式Python版》专栏!关注不迷路~

相关推荐
笨鸟笃行11 分钟前
爬虫第七篇数据爬取及解析
开发语言·爬虫·python
java1234_小锋18 分钟前
一周学会Flask3 Python Web开发-response响应格式
开发语言·python·flask·flask3
大数据追光猿19 分钟前
Python中的Flask深入认知&搭建前端页面?
前端·css·python·前端框架·flask·html5
java1234_小锋19 分钟前
一周学会Flask3 Python Web开发-flask3模块化blueprint配置
开发语言·python·flask·flask3
莫忘初心丶21 分钟前
python flask 使用教程 快速搭建一个 Web 应用
前端·python·flask
不爱学英文的码字机器1 小时前
Python爬虫实战:从零到一构建数据采集系统
开发语言·爬虫·python
鹿鸣悠悠1 小时前
Python 类和对象详解
开发语言·python
laocooon5238578861 小时前
用Python实现的双向链表类,包含了头插、尾插、归并排序等功能
开发语言·python
百锦再1 小时前
在Linux上创建一个Docker容器并在其中执行Python脚本
linux·python·docker
东方芷兰2 小时前
伯克利 CS61A 课堂笔记 12 —— Syntax
笔记·python