[CS] Iterator Pattern(반복자 패턴)

Rosa Damascena·2023년 9월 14일
0

CS

목록 보기
2/4
post-thumbnail

📍 Iterator Pattern


✔️ 반복자 패턴(Iterator Pattern)

→ 반복자 패턴이란

  • 반복자 패턴은 디자인 패턴 중 행동 패턴에 해당하며, 일련의 데이터 집합에 대하여 순차적으로 접근 가능하게 해주는 패턴이다.
  • 이는 컬렉션 구현 방법을 노출시키지 않으면서도 그 집합체 안에 들어있는 모든 항목에 접근할 방법을 제공하는 디자인 패턴이다.

▶︎ 데이터 집합이란 객체들을 그룹으로 묶어 자료의 구조를 취하는 컬렉션을 말한다. 대표적인 컬렉션으로는 리스트, 트리, 그래프, 테이블 등이 있다.

→ 반복자 패턴 구조

  • Aggregate (집합체)
    : Aggregate는 데이터 요소의 집합을 나타내는 인터페이스를 정의한다.
    주로 반복자를 생성하는 메서드(createIterator())를 포함한다.
    Aggregate 인터페이스를 구현한 구체적인 컬렉션 클래스에서 데이터 구조를 관리한다.

  • Iterator (반복자)
    : Iterator는 Aggregate에서 정의한 인터페이스를 구현하며, 데이터 집합 내의 요소를 순회하고 접근하기 위한 메서드를 제공한다.주로 두 가지 메서드를 포함한다. 다음 요소로 이동하고 해당 요소를 반환하는 next() 메서드와 다음 요소의 존재 여부 확인하는 hasNext()가 있다.

  • ConcreteAggregate (구체적인 집합체)
    : ConcreteAggregate는 Aggregate 인터페이스를 실제로 구현한 클래스로, 데이터 구조를 관리하고 Aggregate 인터페이스의 메서드를 구현한다.
    구체적인 컬렉션(예: 리스트, 배열) 내의 데이터를 저장하고 관리한다.
    반복자를 생성하여 ConcreteIterator 객체를 반환한다.

  • ConcreteIterator (구체적인 반복자)
    : ConcreteIterator는 Iterator 인터페이스를 구현한 클래스로, 구체적인 컬렉션을 순회하고 요소에 접근하는 역할을 한다.
    데이터 집합 내의 요소를 순차적으로 탐색하며, next() 메서드로 다음 요소로 이동하고 hasNext() 메서드로 순회 종료 여부를 확인한다.

→ 반복자 패턴 특징

  • 반복자 패턴이 필요한 경우
    - 컬렉션에 상관없이 객체 접근 순회 방식을 통일하고자 할 때

    • 컬렉션을 순회하는 다양한 방법을 사용하고 싶을 때
    • 컬렉션의 복잡한 내부 구조를 클라이언트로부터 숨기고 싶을 때
    • 데이터 저장 컬렉션 종류의 변경 가능성이 있을 때
  • 반복자 패턴의 장점
    - 일관된 iterator interface를 사용해 여러 형태의 컬렉션에 대해 동일한 순회 방법을 제공한다.

    • 컬렉션의 내부 구조와 순회 방식을 숨길 수 있다.
    • 집합체의 구현과 접근하는 처리 부분을 반복자 객체로 분리하여 결합도는 낮출 수 있다.
    • 단일 책임 원칙(SRP)를 준수한다.
    • 개방 폐쇄 원칙(OCP)를 준수한다.
  • 반복자 패턴의 단점
    - 클래스가 늘어나고 복잡도가 증가한다.

    • 간단한 컬렉션만 작동하는 앱의 경우 이 패턴을 사용하면 복잡도만 증가시킬 수 있다.
    • 구현 방법에 따라 캡슐화를 위배할 수 있다.
      • 컬렉션 내부 데이터에 대한 직접적인 접근을 허용하지 않고, 반복자를 통해서만 데이터에 접근하도록 설계해야 한다.

→ 반복자 패턴 구현

# 반복자(Iterator) 인터페이스 정의
class Iterator:
    def __init__(self, collection):
        self.collection = collection  # 데이터 컬렉션을 저장합니다.
        self.index = 0  # 현재 인덱스를 초기화합니다.

    def next(self):
        if self.has_next():
            item = self.collection[self.index]  # 현재 인덱스의 요소를 가져옵니다.
            self.index += 1  # 인덱스를 다음으로 이동합니다.
            return item
        else:
            raise StopIteration()  # 더 이상 요소가 없으면 예외를 발생시킵니다.

    def has_next(self):
        return self.index < len(self.collection)  # 다음 요소가 있는지 여부를 반환합니다.

# 숫자 목록 컬렉션 클래스 정의(Aggregate)
class NumberCollection:
    def __init__(self):
        self.data = []  # 데이터를 저장할 리스트를 초기화합니다.

    def add(self, item):
        self.data.append(item)  # 숫자를 컬렉션에 추가합니다.

    def create_iterator(self):	# ConcreteIterator 생성
        return Iterator(self.data)  # 컬렉션에 대한 반복자를 생성하여 반환합니다.

# 클라이언트 코드
if __name__ == "__main__":
    collection = NumberCollection()  # 숫자 목록 컬렉션 객체를 생성합니다.
    collection.add(1)  # 숫자 1을 컬렉션에 추가합니다.
    collection.add(2)  # 숫자 2를 컬렉션에 추가합니다.
    collection.add(3)  # 숫자 3을 컬렉션에 추가합니다.
	
    # ConcreteAggregate가 ConcreteIterator를 생성하는 부분
    iterator = collection.create_iterator()  # 컬렉션에 대한 반복자를 생성합니다.

    print("숫자 목록 출력:")
    while iterator.has_next():
        print(iterator.next())  # 반복자를 사용하여 숫자 목록을 출력합니다.
from abc import ABC, abstractmethod

# 반복자(Iterator) 인터페이스 정의
class Iterator(ABC):
    @abstractmethod
    def next(self):
        pass

    @abstractmethod
    def has_next(self):
        pass

# Aggregate 인터페이스 정의
class Aggregate(ABC):
    @abstractmethod
    def create_iterator(self):
        pass

# ConcreteAggregate 클래스 정의
class ConcreteNumberCollection(Aggregate):
    def __init__(self):
        self.data = []  # 데이터를 저장할 리스트를 초기화합니다.

    def add(self, item):
        self.data.append(item)  # 숫자를 컬렉션에 추가합니다.

    def create_iterator(self):
        return ConcreteIterator(self)  # ConcreteIterator를 생성하여 반환합니다.

# 구체적인 반복자(ConcreteIterator) 클래스 정의
class ConcreteIterator(Iterator):
    def __init__(self, collection):
        self.collection = collection
        self.index = 0

    def next(self):
        if self.has_next():
            item = self.collection.data[self.index]  # 현재 인덱스의 요소를 가져옵니다.
            self.index += 1  # 인덱스를 다음으로 이동합니다.
            return item
        else:
            raise StopIteration()  # 더 이상 요소가 없으면 예외를 발생시킵니다.

    def has_next(self):
        return self.index < len(self.collection.data)  # 다음 요소가 있는지 여부를 반환합니다.

if __name__ == "__main__":
    collection = ConcreteNumberCollection()
    collection.add(1)
    collection.add(2)
    collection.add(3)

    iterator = collection.create_iterator()

    print("숫자 목록 출력:")
    while iterator.has_next():
        print(iterator.next())  # 반복자를 사용하여 숫자 목록을 출력합니다.

참고

  • Oscar Blancarte
profile
경험 수집가

0개의 댓글