실무 프로젝트로 배우는 Kotlin & Spring/리액티브 프로그래밍

Iterator 패턴

webmaster 2022. 12. 1. 22:05
728x90
  • Iterator 패턴은 데이터의 집합에서 데이터를 순차적으로 꺼내기 위해 만들어진 디자인 패턴이다.
  • Iterator 패턴을 사용하면, 컬렉션이 변경되더라도 동일한 인터페이스를 사용해 데이터를 꺼내올 수 있기 때문에 변경사항 없이 사용할 수 있다.
  • 데이터의 집합이 얼마큼의 크기를 가졌는지 알 수 없는 경우 Iterator 패턴을 사용하면, 순차적으로 데이터를 꺼내 올 수 있다.

Iterator 패턴의 주요 클래스

  • Aggregate는 요소들의 집합체를 나타낸다.
  • Iterator는 집합체 내부에 구현된 Iterator를 이용해 생성한다.
  • Iterator를 사용하는 클라이언트는 생성된 Iterator의 hasNext 함수를 사용해 데이터가 존재하는지 검사하고, next 함수를 사용해 데이터를 꺼낸다.

구현

data class Car(val brand: String)

//Iterable를 구현해 Aggregate를 구현한다,
class CarIterable(val cars: List<Car> = listOf()) : Iterable<Car> {
    override fun iterator(): Iterator<Car> = CarIterator(cars)
}

class CarIterator(val cars: List<Car> = listOf(), var index: Int = 0) : Iterator<Car> {
    override fun hasNext(): Boolean {
        return cars.size > index
    }

    override fun next(): Car {
        return cars[index++] //next를 호출할 때마다, index를 증가
    }
}

fun main() {
    val carIterable = CarIterable(listOf(Car("람보르기니"), Car("페라리")))
    val iterator = carIterable.iterator()
    //Iterator 패턴은 데이터를 저장하는 곳에서 사용하는 곳에 주는 poll 기반, Observer 패턴은 push 기반이다.
    while (iterator.hasNext()) {
        println("브랜드 : ${iterator.next()}")
    }
}
  • CarIterable 클래스는 Iterable 인터페이스를 구현하여, CarsIterator를 생성하는 Iterator 함수를 오버라이드 한다.
  • CarIterator 클래스는 Iterator 인터페이스를 구현하여, 데이터가 존재하는지 확인하는 hasNext, 데이터가 존재하면 데이터를 가져오는 next 함수를 오버라이드 한다.
  • while문 내부에서, hasNext를 통해 데이터를 모두 가지고 올 때까지 반복하고, 데이터를 출력한다.

Observer 패턴과의 차이

  • 데이터를 제공하는 관전에서 Iterator 패턴과, Observer 패턴은 유사하다.
  • Iterator 패턴은 Aggregate이 내부에 데이터를 저장하고, Iterator를 사용해 데이터를 순차적으로 당겨오는 방식으로 pull 방식이다.
  • Observer 패턴은 데이터 제공자가 소비하는 측에 데이터를 통지하는 push 기반이다.
728x90