본문 바로가기
DesignPattern

[Design Pattern] Iterator Pattern

by 봄석 2019. 10. 18.

[Design Pattern] Iterator Pattern

Iterator Pattern(반복자 패턴)에 대하여 알아보고

예제도 java와 kotlin예제를 봐보도록 하겠습니다.

 

 

Iterator Pattern이란?

Iterator Pattern은 접근 기능과 자료구조를 분리시켜 객체화합니다.

서로 다른 구조를 가지고 있는 저장 객체에 대해서  접근하기 위해서  interface를 통일시키고 싶을 때 주로  사용합니다.

 

 ex)

for(int i=0;i<arr.length;i++){
	System.out.println(arr.get(i);
}

위의 코드와 같이 배열 요소에 접근하기 위한 반복문이 있을 때 ,

여기서 arr의 타입이 배열이 아닌 다른  자료구조로  바뀌어야 한다면 , 위의 반복문 코드는 수정되어야 합니다.

수정되기 위해서는   arr.length의 사이즈를 알아야 하고, arr.get(i)와 같은 컬렉션에 대한 접근방법을 알아야 합니다.

수정하기 위해 위와 같은 변화의 필요 없이 흔하게 쓰는 반복 기능만 통일하여 쓰고자 할 때 

Iterator는 이러한 자료구조에 상관없이 객체 접근 방식을 통일하고자 할 때 사용할 수 있습니다.

 

 

Iterator : 집합체의 요소들을 순서대로 검색하기 위한 인터페이스 정의

 

● ConcreateIterator : Iterator 인터페이스를 구현함

 

● Aggregate(골재) : 여러 요소들로 이루어져 있는 집합체

 

● ConcreateAggregate : Aggreagate 인터페이스를 구현하는 클래스

 

 

 

Iterator Pattern with Java

public interface Animal {
    public void eat();
    public void sleep();
    public void sound();
}
public class Sheep implements Animal {
    @Override
    public void eat() {
        System.out.println("길쭉한 풀 뜯어먹음");
    }
 
    @Override
    public void sleep() {
        System.out.println("앉아서 잠");
    }
 
    @Override
    public void sound() {
        System.out.println("메에에");
    }
}
public class Goat implements Animal {
    @Override
    public void eat() {
        System.out.println("짧은 풀 뜯어먹음");
    }
 
    @Override
    public void sleep() {
        System.out.println("엎드려서 잠");
    }
 
    @Override
    public void sound() {
        System.out.println("음메에에");
    }
}
public class Goatherd {
 
    public static final int MAX_GOATS = 100;
    private int goatNum = 0;
    public static final HashMap<Integer, Goat> GOATS = new HashMap<>();
 
    public Goatherd() {
        super();
        int i;
 
        for (i = 0; i < 30; ++i) {
            GOATS.put(i, new Goat());
 
        }
 
        goatNum = i;
    }
 
    public void addGoat() {
        if (GOATS.size() <= MAX_GOATS) GOATS.put(goatNum++, new Goat());
    }
 
    public void removeGoat() {
        GOATS.remove(goatNum--);
    }
    
    public Iterator<Integer> createIterator() {
        return GOATS.keySet().iterator();
    }

}
public class SheepIterator implements Iterator<Sheep> {
 
    private Sheep[] sheeps;
    int position = 0;
 
    public SheepIterator(Sheep[] sheeps) {
        super();
        this.sheeps = sheeps;
 
    }
 
    @Override
    public boolean hasNext() {
        if (position >= sheeps.length || sheeps[position] == null) {
            return false;
 
        } else {
            return true;
        }
    }
 
    @Override
    public Sheep next() {
        Sheep tempSheep = sheeps[position];
        position++;
        return tempSheep;
    }
}
public class Client {
    public static void main(String[] args) {

        Goatherd goatherd = new Goatherd();
        Shepherd shepherd = new Shepherd();

        Iterator<Integer> goatIter = goatherd.createIterator();
        Iterator<Sheep> sheepIter = shepherd.createIterator();

        while(goatIter.hasNext()) {
            Goat goat = goatherd.GOATS.get(goatIter.next());
            goat.sound();
        }

        while(sheepIter.hasNext()) {
            Sheep sheep = sheepIter.next();
            sheep.sound();
        }
    }
}

goat는 자바에서 제공하는 hashMap의 Iterator를( 내부에 Iterator <E> 인터페이스를 구현하고있습니다.) 

SheapIterator는 Iterator<E> 인터페이스를 구현하여 만든 Iterator입니다.

 

Aggregate는  Goatherd(염소 치기 , 염소의 집합), Shepherd(양치기, 양의 집합)

Iterator는 SheapIterator

입니다.

 

염소와 양 모두 동일한 방식으로 서로의 집합 객체들에 접근이 가능합니다.

 

 

Iterator Pattern with Kotlin 

typealias Fruit = String

operator fun Fruits.iterator(): Iterator<Fruit> = FruitsIterator(this)
class Fruits(vararg val fruits: Fruit)
class FruitsIterator(container: Fruits) : Iterator<Fruit> {
    private val iterator = container.fruits.iterator()

    override fun hasNext(): Boolean = iterator.hasNext()
    override fun next(): Fruit = iterator.next()

}

 

class IteratorTest {

    @Test
    fun givenAggregateWithIterator_whenTraverseAggregateInForLoop_thenReturnAggregateComponentValues() {
        // Given
        val fruits = Fruits("apple", "banana", "orange").iterator()

        // When
        val values: MutableList<Fruit> = mutableListOf()
        for (fruit in fruits) values.add(fruit)

        // Then
        val expectedValues = listOf<Fruit>("apple", "banana", "orange")
        assertThat(values, CoreMatchers.equalTo(expectedValues))
    }
}

 

 

 

정리

반복자 패턴(Iterator Pattern)은 모든 집합체에 대하여 동일한 인터페이스로 모든 원소를 순회할 수 있도록 해줍니다.

 

반복자 패턴을 사용하기 위해서는 Iterator 인터페이스를 구현한 클래스를 만들어서 해당 자료구조나 집합체가 가진 모든 원소를 순회할 수 있는 기능을 정의해야 합니다.

 

사용할 집합체 안에이터레이터를 만드는 메서드를 제공하여야 한다. (Iterater <E> implement)

 

 

샘플 보러 가기

https://github.com/qjatjr1108/DesignPattern

 

qjatjr1108/DesignPattern

DesignPattern Sample. Contribute to qjatjr1108/DesignPattern development by creating an account on GitHub.

github.com

 

'DesignPattern' 카테고리의 다른 글

[Design Pattern] Command Pattern  (0) 2019.10.21
[Design Pattern] Interpreter Pattern  (0) 2019.10.21
[Design Pattern] Mediator Pattern  (0) 2019.10.18
[Design Pattern] Memento Pattern  (0) 2019.10.17
[Design Pattern] Observer Pattern  (0) 2019.10.15

댓글