개발/디자인패턴

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

nova_dev 2022. 3. 18. 00:00
반응형

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

반복자 패턴은 내부 구조를 노출하지 않고 집합체를 통해 원소 객체에 순차적으로 접근할 수 있는 방법을 제공한다.

 

 반복자 패턴이란?

  • 반복자 패턴은 순한 알고리즘이 실제 구현된 객체에 의존하지 않고, 독립적인 동작을 유지하기 위해 객체의 내부 메서드에 직접 접근하지 않는다. 대신 반복자의 메서드를 호출하여 처리한다.

 

 

 반복자 패턴 구조

  • Iterator
    • 집합체의 요소들을 순서대로 검색하기 위한 인터페이스
  • ConcreateIterator
    • Iterator 인터페이스 구현
  • Aggregate
    • 여러 요소들로 이루어져 있는 집합체
  • ConcreateAggregate
    • Aggreagate 인터페이스를 구현하는 클래스

 반복자 패턴 예시 코드 구조

팀에는 여러 Worker가 있다. 이런 상황에서 팀원들에게 공통적인 행동을 반복적으로 수행할 수 있게 Iterator를 제공한다.
(일반적인 상황에서는 Worker를 배열이 아니라 이미 Iterator를 구현하고 있는 Collection을 사용할 것 같지만(List 등), 예제를 위해 배열로 선언하고 예제 코드를 짜보았다.)

 반복자 패턴 코드

1. WorkerType enum 클래스

public enum WorkerType {
    DEVELOPER("DEVELOPER", "개발자"),
    MANAGER("MANAGER", "매니저"),
    QA("QA", "QA"),
    PLANNER("PLANNER", "기획자");
    private final String code;
    private final String value;


    WorkerType(String code, String value) {
        this.code = code;
        this.value = value;
    }

    public String getCode() {
        return code;
    }

    public String getValue() {
        return value;
    }
}

2. Worker 클래스

public class Worker {
    private final String name;
    private final WorkerType type;

    public Worker(String name, WorkerType type) {
        this.name = name;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public WorkerType getType() {
        return type;
    }
}

3. Aggregate 인터페이스

import java.util.Iterator;

public interface Aggregate<T> {
    Iterator<T> iterator();
}

4. Aggregate를 구현하는 Team 클래스
Worker 배열을 들고 있으며, Worker를 순회할 수 있는 메서드를 iterator를 제공한다.

public class Team implements Aggregate<Worker> {
    private final Worker[] workers;
    private final String name;
    private int lastIndex = 0;

    public Team(String name, int size) {
        this.name = name;
        workers = new Worker[size];
    }

    public void addTeamMember(Worker worker) {
        if (lastIndex < workers.length) {
            this.workers[lastIndex] = worker;
            lastIndex++;
        } else {
            System.out.println("팀의 정원이 꽉 찼습니다.");
        }
    }


    public Worker getWorker(int index) {
        return workers[index];
    }

    public int getSize() {
        return workers.length;
    }

    public String getName() {
        return name;
    }

    @Override
    public Iterator<Worker> iterator() {
        return new TeamIterator(this);
    }

}

5. Team을 순회할 수 있는 기능을 제공하는 TeamIterator 클래스

public class TeamIterator implements Iterator<Worker> {
    private final Team team;
    private int index;

    public TeamIterator(Team team) {
        this.team = team;
        this.index = 0;
    }

    @Override
    public boolean hasNext() {
        return index < team.getSize();
    }

    @Override
    public Worker next() {
        Worker worker = team.getWorker(index);
        index++;
        return worker;
    }
}

6. Team을 순회하는 반복자 패턴 테스트 코드

class TeamTest {

    @Test
    @DisplayName("팀 반복 테스트")
    void teamTest() {
        Team team = new Team("TF팀", 5);
        team.addTeamMember(new Worker("이모씨", WorkerType.MANAGER));
        team.addTeamMember(new Worker("김모씨", WorkerType.DEVELOPER));
        team.addTeamMember(new Worker("송모씨", WorkerType.DEVELOPER));
        team.addTeamMember(new Worker("임모씨", WorkerType.PLANNER));
        team.addTeamMember(new Worker("장모씨", WorkerType.QA));

        System.out.println("팀 이름: " + team.getName());

        Iterator<Worker> iterator = team.iterator();
        while (iterator.hasNext()) {
            Worker worker = iterator.next();
            System.out.println("-------------");
            System.out.println("이름: " + worker.getName());
            System.out.println("직업: " + worker.getType().getValue());
        }
    }

}

결과

팀 이름: TF팀
-------------
이름: 이모씨
직업: 매니저
-------------
이름: 김모씨
직업: 개발자
-------------
이름: 송모씨
직업: 개발자
-------------
이름: 임모씨
직업: 기획자
-------------
이름: 장모씨
직업: QA

 그렇다면 우리가 일반적으로 사용하는 ArrayList는?

ArrayList도 Collection을 구현했기 때문에 결국 최상위로 올라가 보면 Iterable을 구현하고 있는 것을 볼 수 있다.
알고 보면 우리도 모르게 ArrayList를 사용할 때마다 반복자 패턴을 사용하고 있던 것.

보통 이미 만들어진 Collection을 사용하지만, 커스터마이징 한 컬렉션을 사용해야 한다거나 직접 Iterator를 구현해서 반복하는 것이 효과적일 때 사용할 법하다.

 Github 코드

Github 예제 코드 링크

Github 예제 테스트 코드 링크

참고 자료

 

 

 

 

 

반응형