본문 바로가기

디자인 패턴

디자인 패턴 - 반복자 패턴(Iterator Pattern)

1. 정의

  • 컬렉션의 구현 방법을 노출하지 않으면서 집합체 내의 모든 항목에 접근하는 방법을 제공한다.

2. 예시

  • 식당의 점심 메뉴는 리스트에 저장되어 있고, 저녁 메뉴는 배열에 저장되어 있다. 같은 방법으로 점심 및 저녁 메뉴를 가져온다.

3. 그림

4. 클래스 다이어그램

5. 코드

import java.util.Arrays;
import java.util.Iterator;

public class Client {
    public static void main(String[] args){

        System.out.println("[직접 만든 반복자 패턴]");
        LunchMenu lunchMenu = new LunchMenu();
        MenuIterator lunchIterator = lunchMenu.createIterator();
        printAllMenu(lunchIterator);

        System.out.println("------");

        DinnerMenu dinnerMenu = new DinnerMenu();
        MenuIterator dinnerIterator = dinnerMenu.createIterator();
        printAllMenu(dinnerIterator);

        System.out.println("\\n[자바에서 제공하는 반복자 패턴]");
        Iterator<MenuItem> lunch = lunchMenu.getMenuItems().iterator();
        javaIterator(lunch);
        
        System.out.println("------");

        Iterator<MenuItem> dinner = Arrays.stream(dinnerMenu.getMenuItems()).iterator();
        javaIterator(dinner);

    }

    private static void printAllMenu(MenuIterator iterator){
        while (iterator.hasNext()){
            MenuItem item = iterator.next();
            System.out.println(item.getName() + " : " + item.getPrice());
        }
    }

    private static void javaIterator(Iterator<MenuItem> iterator){
        while (iterator.hasNext()){
            MenuItem item = iterator.next();
            System.out.println(item.getName() + " : " + item.getPrice());
        }
    }
}
/* 출력
[직접 만든 반복자 패턴]
팬케이크 : 100
와플 : 200
팬케이크+와플 : 250
딸기 요거트 : 50
------
불고기 : 300
비빔밥 : 200
식혜 : 30

[자바에서 제공하는 반복자 패턴]
팬케이크 : 100
와플 : 200
팬케이크+와플 : 250
딸기 요거트 : 50
------
불고기 : 300
비빔밥 : 200
식혜 : 30
*/
public class MenuItem {
    String name;
    int price;

    public MenuItem(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public int getPrice() {
        return price;
    }
}
public interface MenuIterator {
    boolean hasNext();
    MenuItem next();
}
import java.util.List;

public class LunchMenuIterator implements MenuIterator {
    List<MenuItem> menuItems;
    int pos = 0;

    public LunchMenuIterator(List<MenuItem> menuItems) {
        this.menuItems = menuItems;
    }

    @Override
    public boolean hasNext() {
        if(pos>= menuItems.size()) {
            return false;
        }
        return true;
    }

    @Override
    public MenuItem next() {
        return menuItems.get(pos++);
    }
}
public class DinnerMenuIterator implements MenuIterator {
    MenuItem[] menuItems;
    int pos = 0;

    public DinnerMenuIterator(MenuItem[] menuItems) {
        this.menuItems = menuItems;
    }

    @Override
    public boolean hasNext() {
        if(pos>= menuItems.length || menuItems[pos] == null){
            return false;
        }
        return true;
    }

    @Override
    public MenuItem next() {
        return menuItems[pos++];
    }
	}
import java.util.List;

public class LunchMenu {
    List<MenuItem> menuItems = List.of(
            new MenuItem("팬케이크", 100),
            new MenuItem("와플", 200),
            new MenuItem("팬케이크+와플", 250),
            new MenuItem("딸기 요거트", 50)
    );

    public List<MenuItem> getMenuItems() {
        return menuItems;
    }

    public MenuIterator createIterator(){
        return new LunchMenuIterator(menuItems);
    }
}
public class DinnerMenu {
    MenuItem[] menuItems = new MenuItem[]{
            new MenuItem("불고기", 300),
            new MenuItem("비빔밥", 200),
            new MenuItem("식혜", 30),
    };

    public MenuItem[] getMenuItems() {
        return menuItems;
    }

    public MenuIterator createIterator(){
        return new DinnerMenuIterator(menuItems);
    }

}

https://github.com/kang-seongbeom/design_pattern

💡 Github에서 디자인 패턴 코드를 볼 수 있습니다.

6. 설명

  • MenuIterator의 사용으로, 리스트인 LunchMenu와 배열인 DinnerMenu에 일관되게 접근할 수 있다.
  • java의 리스트는 Iterator를 구현하고 있고, 배열은 Stream을 통해 Iterator로 변환할 수 있다.
// 리스트 
Iterator<MenuItem> lunch = lunchMenu.getMenuItems().iterator(); 
// 배열 
Iterator<MenuItem> dinner = Arrays.stream(dinnerMenu.getMenuItems()).iterator();