Design Patterns @ Python – Iterator 迭代器模式筆記

設計模式 – Iterator 迭代器模式

什麼是 Iterator 迭代器模式?

  • Iterator 迭代器模式是一種設計模式, 允許程序以一致的方式 訪問集合物件中的元素,而不需要了解集合物件的底層表示 (隱藏接口以外的細節)
  • Iterator 迭代器模式將 集合物件的訪問接口與內部表示分離 ,從而能 在不影響集合物件其他操作的情況下,支持多種 遍歷 方式。
    • 它定義了一個迭代器接口(Interface),該接口用於訪問集合元素
    • 集合物件實現該接口來返回迭代器實例(Instance)
    • 客戶通過迭代器訪問集合元素,而 不需要了解集合的底層結構

Iterator 模式的 UML 架構圖

classDiagram
    ConcreteIterator <|-- Iterator
    Container <|-- Iterator
    ConcreteContainer <|-- Iterator
    Iterator: +__next__()
    Iterator: + __iter__() 
    class ConcreteIterator{
      +__next__():Object
      + __iter__():Object
    }
    class Container{
      +ConcreteIterator():Iterator
    }
    class ConcreteContainer{
      +ConcreteIterator():Iterator
    }
  • 說明:
    • Iterator 是抽象類別,定義了遍歷容器的通用方法,包括 __next__() (一定要有))和 __iter__() (不一定要有),只要有 __next__() 就能 for loop 進行迭代。
    • ConcreteIterator 是具體類別,實現了 Iterator 中的抽象方法。
    • Container 是抽象類別,定義了創建 Iterator 的接口。
    • ConcreteContainer 是具體類別,實現了 Container 中的接口。

範例說明:

from collections.abc import Iterator

class Student:
    '''
    定義一個目標物件
    '''
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def get_name(self):
        return self.name

    def get_age(self):
        return self.age


class ClassroomIterator(Iterator):
    '''
    實現一個迭代器類
    '''    
    def __init__(self, classroom):
        self.classroom = classroom
        self.index = 0

    def __next__(self):
        try:
            student = self.classroom.get_student_at(self.index)
        except IndexError:
            raise StopIteration()
        self.index += 1
        return student

class Classroom:
    '''
    將物件集合使用迭代器封裝起來
    '''
    def __init__(self):
        self.students = []

    def add_student(self, student):
        self.students.append(student)

    def get_student_at(self, index):
        return self.students[index]

    def get_size(self):
        return len(self.students)

    def create_iterator(self):
        return ClassroomIterator(self)

def main():
    classroom = Classroom()
    classroom.add_student(Student("Alice", 20))
    classroom.add_student(Student("Bob", 21))
    classroom.add_student(Student("Charlie", 22))

    iterator = classroom.create_iterator()
    while True:
        try:
            student = next(iterator)
            print(student.get_name() + ": " + str(student.get_age()))
        except StopIteration:
            break

if __name__ == "__main__":
    main()
# 執行結果:
# Alice: 20
# Bob: 21
# Charlie: 22

使用迭代器模式的目標對象、使用時機及優缺點:

  • 目標對象: 當需要遍歷容器的程式碼時~

  • 使用時機: 當容器的底層表示形式不應該對使用者公開時。

  • 優點:
    • 封裝了集合物件迭代器的表示,使客戶端可以獨立於集合的結構進行遍歷
    • 支持多種 遍歷 方式,通過實作不同的迭代器可以添加新的 遍歷 方式
    • 訪問不同的集合結構 提供一致的接口
    • 增加了對集合的可擴展性不需要修改集合就可以添加新的遍歷方式

  • 缺點:
    • 增加了類的複雜度,需要為每一種集合物件實作一個對應的迭代器。
    • 遍歷非常簡單的集合物件時可能感覺迭代器模式比直接遍歷效率還要低。
1個讚