suyeonme

[디자인 패턴] 반복자 패턴(Iterator Pattern) 본문

프로그래밍👩🏻‍💻/디자인 패턴

[디자인 패턴] 반복자 패턴(Iterator Pattern)

suyeonme 2022. 8. 9. 09:50
헤드 퍼스트 디자인 패턴을 읽고 정리한 내용입니다.

반복자 패턴이란?


반복자 패턴은 컬렉션의 구현 방법을 노출하지 않으면서 집합체 내의 모든 항목에 접근하는 방법을 제공한다. 반복자 패턴은 Iterator 인터페이스에 의존한다.

* 컬렉션(collection)은 집합체(aggregate)라고도 불리운다.

* java.util.Iterator는 Iterator 인터페이스를 제공한다.

이미지출처: https://miro.medium.com/max/1051/1*7sFKQXqnxmtxedGacNGr-A.png

반복자 패턴 사용시 이점

  1. 컬렉션 객체 안에 들어있는 모든 항목에 접근하는 방식이 통일되어있으면 종류에 관계없이 모든 집합체에 사용할 수 있는 다형적인 코드를 만들 수 있다.
  2. 모든 항목에 일일히 접근하는 작업을 컬렉션 객체가 아닌 반복자 객체가 맡는다. 따라서 집합체의 인터페이스와 구현이 간단해지고 집합체는 반복작업이 아닌 자신의 일에 집중할 수 있다.

반복자 패턴 예제


MenuItem 클래스

public class MenuItem {
 String name;
 String description;
 boolean vegitarian;
 double price;
 
 public MenuItem(String name, String description, boolean vegitarian, double price) {
   this.name = name;
   this.description = description;
   this.vegitarian = vegitarian;
   this.price = price;
 }
 
 String getName() {
   return name;
 }
  
 String getDescription() {
   return description;
 }
 
  String getPrice() {
   return price;
 }
 
 boolean isVegitarian() {
   return vegitarian;
 }
}

DinnerMenu 클래스

각각 다른 컬렉션을 사용하여 메뉴를 저장하지만 컬렉션의 종류와 상관없이 반복자를 구현한다. 

  • Array에는 iterator()  메소드가 존재하지 않으므로 따로 반복자를 구현해야한다.
  • ArrayList, HashMap등의 컬렉션 객체는 iterator 메소드를 사용하면 된다.
public class DinerMenu implements Menu {
  static final int MAX_ITEMS = 6;
  int numberOfItems = 0;
  MenuItem[] menuItems; // Array 사용
  // ...
  
  public Iterator createIterator() { // (*)
    return new DinerMenuIterator(menuItems);
  }
}

public class PancakeHouseMenu implements Menu {
  List<MenuItem> menuItems; // ArrayList 사용
  // ...
 
  public Iterator<MenuItem> createIterator() { // (*)
    return menuItems.iterator();
  }
}

public class CafeMenu implements Menu {
  Map<String, MenuItem> menuItems = new HashMap<String, MenuItem>(); // HashMap 사용
  // ...
 
  public Iterator<MenuItem> createIterator() { // (*)
    return menuItems.values().iterator();
  }
}

DinnerMenuIterator 클래스

public interface Iterator {
  boolean hasNext();
  MenuItem next();
}

public class DinerMenuIterator implements Iterator {
  MenuItem[] items;
  int position = 0;
  
  public DinerMenuIterator(MenuItem[] items) {
    this.items = items;
  }
  
  public MenuItem next() {
    MenuItem menuItem = items[position];
    position = position + 1;
    return menuItem;
  }
  
  public boolean hasNext() {
    if(position >= items.length || items[position] == null) {
      return false;
    } else {
      return true;
    }
  }
}

종업원 코드

import java.util.Iterator;

public class Waitress {
  List<Menu> menus;
  
  public Waitress(List<Menu> menus) {
    this.menus = menus;
  }
  
  public void printMenu() {
    Iterator<Menu> menuIterator = menus.iterator();

    while(menuIterator.hasNext()) {
      Menu menu = menuIterator.next();
      printMenu(menu.createIterator());
    }
  }  
  
  public void printMenu(Iterator iterator) {
	while(iterator.hasNext()) {
      MenuItem menuItem = iterator.next();
      System.out.print(menuItem.getName());
    }
  }
}

public class MenuTestDrive {
  public static void main(String args[]) {
    PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
    DinerMenu dinerMenu = new DinerMenu();
    CafeMenu cafeMenu = new CafeMenu();
    
    List<Menu> menus = new ArrayList<Menu>();
    menus.add(pancakeHouseMenu);
    menus.add(dinerMenu);
    menus.add(cafeMenu);
        
    Waitress waitress = new Waitress(menus);
    waitress.printMenu();
  }
}

 

Comments