Home 행위패턴 - 이터레이터 패턴
Post
Cancel

행위패턴 - 이터레이터 패턴

Iterator Pattern 🧙‍♂️

디자인 패턴이란?

디자인 패턴이란?

  • 디자인 패턴은 소프트웨어 공학의 소프트웨어 설계에서 공통으로 발생하는 문제를 자주 쓰이는 설계 방법을 정리한 패턴이다.
  • 디자인 패턴을 참고하여 개발하면 효율성과 유지보수성, 운용성이 높아지며, 프로그램 최적화가 된다고 한다.

디자인 패턴을 목적과 범위로 나눌수 있다

구분유형설명
 생성객체 인스턴스 생성에 관여, 클래스 정의와 객체 생성 방식을 구조화, 캡슐화를 수행
목적구조더 큰 구조 형성 목적으로 클래스나 객체의 조합을 다루는 패턴
 행위클래스나 객체들이 상호작용하는 방법과 역할 분담을 다루는 패턴
범위클래스클래스간 관련성(상속), 컴파일 시 정적으로 결정
 객체객체 간 관련성을 다루는 패턴, 런타임 시 동적으로 결정

  

이터레이터 패턴 반복작업을 이터레이터에게 맡겨서 반복작업을 순서대로 처리하는 패턴

  

이터레이터 패턴 반복작업을 이터레이터에게 맡겨서 반복작업을 순서대로 처리하는 패턴 {: .prompt-tip}## <span style="color: gold"> 이터레이터 패턴이란? Iterator pattern

이터레이터 패턴은 컬렉션 구현 방법을 노출시키지 않으면서도 그 집합체 안에 들어있는 모든 항목에 대해 접근할 수 있게 해준다. 또한, 모든 항목에 일일이 접근하는 컬랙션 객체가 아닌 반복자 객체가 맡고 진행한다는 점이다.(Stream같은 내부반복자는 아님) 이를 통해 인터페이스와 구현이 단순해진다. 우선 이터레이터의 기본 사용법을 설명하고 이터레이터 패턴을 알아보자.

이터레이터 기본 구성

1
2
3
4
5
6
7
8
9
10
11
12
13
class AboutIterator{
    public static void main (String[] args){
        ArrayList list = new ArrayList();
        list.add("1"); ... list.add("5"); // 1~5까지 넣었다고 가정

        Iterator it = list.iterator();

        while(it.hasNext()){
            Object obj = it.next();
            System.out.print(obj+" "); //1 2 3 4 5
        }
    }
}

한 방향으로만 사용하는 이터레이터 외에 반대방향으로도 하는 사용할 수 있는 List iterator도 있다. next()대신 preivous()를 사용하면된다.

리스트 이터레이터 구성 ListIterator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class AboutIterator{
    public static void main (String[] args){
        ArrayList list = new ArrayList();
        list.add("1"); ... list.add("5"); // 1~5까지 넣었다고 가정

        ListIterator it = list.listIterator();

        while(it.hasNext()){
            Object obj = it.next();
            System.out.print(obj+" "); //1 2 3 4 5
        }

           while(it.hasPrevious()){
            Object obj = it.pervious();
            System.out.print(obj+" "); //5 4 3 2 1 역방향
        }
    }
}

자 이번에는 이터레이터 패턴을 이용해보겠다. 필자는 요새 향수가 너무 많아서 향수를 한번 정리하는겸 향수로 예제를 만들겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.util.Iterator;
//까먹지 않고 이터레이터를 쓰기 위한 인터페이스
interface makeIteratorInterface{
    Iterator createIterator();
}
//향수이름과 브랜드를 저장하는 객체
public class Perfume {
    private String name;
    private String brand;

    public String getName() {
        return name;
    }

    public String getBrand() {
        return brand;
    }

    public Perfume(String brand, String name) {
        this.name = name;
        this.brand = brand;
    }
//향수를 보관하는 수납장이다.
    private static class Closet implements makeIteratorInterface{
        private Perfume[] perfumes;
        private int location = 0; //향수 마지막 위치

        public Perfume getPerfume(int location) {
            return perfumes[location];
        }

        public int getLocationSize() {
            return location;
        }

        public void collectPerfume(Perfume perfume) {
            if (location < perfumes.length) {
                this.perfumes[location] = perfume;
                location++;
            }else
                System.out.println("수납장이 꽉찼습니다.");
        }

        public Closet(int total) { //향수 총개수
            perfumes = new Perfume[total];
        }

        @Override
        public Iterator createIterator() {
            return new ClosetIterator(this);
        }

수납장에서 하나씩 애들을 어떻게 꺼낼지 정책을 결정하는 이터레이터 패턴의 예.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        private class ClosetIterator implements Iterator<Perfume> {
            private Closet closet;
            private int currentLocation = 0;
            public ClosetIterator(Closet closet) {
                this.closet = closet;
            }

            @Override
            public boolean hasNext() {
                return currentLocation < closet.getLocationSize();
            }

            @Override
            public Perfume next() {
                Perfume perfume = closet.getPerfume(currentLocation);
                currentLocation++;
                return perfume;
            }
        }

정답을 출력하는 메서드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
      
        public static void main(String[] args) {
            Closet closet = new Closet(4);
            Perfume perfume1 = new Perfume("입셍로랑", "옴므");
            Perfume perfume2 = new Perfume("베르사체", "에로스");
            Perfume perfume3 = new Perfume("디올", "세비지");
            Perfume perfume4 = new Perfume("샤넬", "옴므");
            Perfume perfume5 = new Perfume("에르메스", "옴므");
          

            closet.collectPerfume(perfume1); closet.collectPerfume(perfume2);
            closet.collectPerfume(perfume3); closet.collectPerfume(perfume4);
            closet.collectPerfume(peffume5);

            System.out.println("현재 향수 개수 = " + closet.getLocationSize());

            Iterator iterator = closet.createIterator();
            while (iterator.hasNext()) {
                Perfume next = (Perfume) iterator.next();
                System.out.println(next.brand+" "+next.name);
            }
        }
    }
}
//수납장이 꽉찼습니다. (에르메스가 못들어감.)
//현재 향수 개수 = 4
// 입셍로랑 옴므
// 베르사체 에로스
// 몽블랑 세비지
// 샤넬 옴므

<span style="color: gold"> 장점 단점

장점

  • 위에서 언급한 것처럼 모든 항목을 일일히 접근하여 작업을 하는 것이 아닌, 이터레이터가 모든 항목에 대해 접근할 수 있도록 해준다.
  • 클래스의 응집도가 올라간다. (응집도: 한 모듈 내부의 처리 요소들이 서로 관련되어 있는 정도)

단점

  • 사실 지금과 같은 단순한 반복이라면 복잡하기만하고 필요성이 없는거 같다.

<span style="color: gold"> 출처

  • Head First 디자인패턴
This post is licensed under CC BY 4.0 by the author.