dh_0e

[Design Pattern] Behavior Design Patterns II (Interpreter Pattern, Iterator Pattern) 본문

Software Analysis & Design/Design Patterns

[Design Pattern] Behavior Design Patterns II (Interpreter Pattern, Iterator Pattern)

dh_0e 2025. 11. 19. 23:54

해석자 패턴(Interpreter Pattern)

  • 언어(language)의 문법 규칙을 표현하고 해당 언어의 문법 규칙(grammar rules)을 클래스로 표현하고, 이 클래스들을 조합하여 해당 언어의 문장을 해석하는 데 사용되는 행동 패턴
  • 주요 용도: 컴파일러 또는 인터프리터를 개발할 때 언어의 문법 구조를 나타내는 데 유용함
  • 특징: 새로운 언어를 추가하거나 기존문법을 변경할 때 유연하게 확장 가능
    • ex) 정규 표현식, 후위 표기법

  •  

Posfix Expression(후위 표기법) 예제

구분 Infix Notation (중위 표기법) Postfix Notation (후위 표기법)
특징 사람들이 보기에 익숙함 사람이 보기에 직관적이지 않지만, 계산이 쉬움
괄호/우선순위 연산자 우선순위 때문에 괄호가 필요함 (처리 복잡) 수식에 괄호가 필요 없으며, 수식 자체에 연산자 우선순위가 포함되어 표현됨
예시 (2 + 4) * (3 + 4) 2 4 + 3 4 + *

 

  • 특정 연산자는 가장 마지막으로 등장한 두 피연산자에 대한 계산
  • 가장 마지막으로 등장한 피연산자(결과값)을 파악하기 위해 스택을 활용

Interpreter 패턴 도입 전 기존 코드

  • Context: [x=5, y=10] 같은 context 정보가 담겨있음
  • Expression: 표현하는 문법을 나타내는데 context를 참조해서 해석하는 interpret(Context) 함수를 가짐
  • TerminalExpression: (x, y, z) 처럼 Subtree가 될 수 있으며 그 자체로 종료될 수 있음
  • NonTerminalExpression: (+, -)처럼 다른 expression들을 재귀적으로 참조하는 객체

책임자 패턴 예시 코드(Client)
책임자 패턴 예시 코드(Terminal expression)
책임자 패턴 예시 코드(Nonterminal expression)
책임자 패턴(parser)

진행 과정

 

  • 장점(Pros)
    • 새로운 언어 요소나 문법 규칙 추가에 유연함
    • 단순한 문법을 가진 언어에 효과적
    • 언어 문법/규칙 변경에 대응하기 쉬움
  • 단점(Cons)
    • 언어 문법이 복잡한 경우 클래스 계층 구조가 복잡해짐
      • C언어 같은 경우 컴파일러가 오버헤드 엄청 커짐
    • 일부 복잡한 언어나 대규모 문장에 대해 성능 저하 가능성 있음

 


 

반복자 패턴(Iterator Pattern)

  • 컬렉션(collection) 요소들의 기본 표현(리스트, 스택, 트리 등)을 외부에 노출하지 않고, 컬렉션 내 요소를 하나씩 순회할 수 있도록 하는 행동 패턴

  • 필요성: 다양한 자료구조(선형/비선형)에 관계없이 클라이언트가 일관된 방식으로 요소 조회를 할 수 있도록 함
    • 선형적인 자료구조(배열, 리스트 등)는 순차적으로 요소 조회를 할 수 있지만, 트리, 해시와 같은 비선형적인 자료구조는 순회의 기준이 필요

  • 아이디어: 컬렉션의 순회 동작 Iterator(반복자)라는 별도 객체로 추출

Iterator Pattern 구조 예시(Tree-DFS, BFS)
Iterator Pattern 구조

역할 설명
Iterator (인터페이스) 컬렉션 순회에 필요한 작업(예: hasNext(), next()) 선언
ConcreteIterator (구현체) 컬렉션 순회를 위한 특정 알고리즘 구현 (실제 데이터 접근 및 위치 관리)
IterableCollection (인터페이스) 컬렉션과 호환되는 반복자를 가져오기 위한 메서드 (iterator()) 선언
ConcreteCollection (구현체) ConcreteIterator 클래스의 새 인스턴스를 반환 (iterator() 메서드 구현)

 

Iterator Pattern 코드 예시(IterableCollection & ConcreteCollection)
Iterator Pattern 코드 예시(Iterator & ConcreteIterator)

  • 다른 복잡한 자료구조가 들어온다면 hasNext()를 수정하여 구현

Iterator Pattern 코드 예시 (Client)

 

JAVA에서 반복자 패턴이 적용된 사례

java.util.Iterator

  • hasNext(): 순회할 요소가 남아있는지 확인
  • next(): 현재 커서의 요소를 반환하고 다음 위치로 커서를 이동
  • remove(): next()로 받았던 해당 요소를 삭제 (지원되는 컬렉션에 한함)
    • 보통 동시 다발적으로 같은 명령을 수행해도 안전한 컬렉션에서 제공 

java.util.Iterator

  • forEachRemaining(): 함수형 인터페이스를 통해 남아있는 요소를 순회하는 코드를 단순하게 만듦

 

Iterator Pattern 장단점

  • 장점(Pros)
    • 일관된 순회 인터페이스 제공(다양한 컬렉션에 대해 동일)
    • 클라이언트는 컬렉션 내부 구조 및 순회 방식을 알 필요 없음(결합도 낮춤)
    • 컬렉션의 구현과 접근하는 부분을 반복자로 분리
  • 단점(Cons)
    • 앱이 간단한 컬렉션에서만 작동하는 경우 코드가 복잡해짐
    • 반복자 객체를 만드는 것이 불필요할 수 있음
      • 그냥 배열 같은 경우 portable 사용하면 됨

 


 

Summary

  • 해석자 패턴(Interpreter Pattern)
    • 언어(language)의 문법 규칙을 표현하고 해당 언어의 해석을 하는데 사용되는 행동 패턴 
  • 반복자 패턴(Iterator Pattern)
    • 컬렉션 (collection) 요소들의 기본 표현 (리스트, 스택, 트리 등)을 노출하지 않고 컬렉션 내 요소를 하나씩 순회할 수 있도록 하는 행동 패턴