[디자인 패턴(Design Pattern)] 옵저버(Observer)

업데이트:

카테고리:

태그:


옵저버 패턴이란?

옵저버 패턴이란 행위 패턴 중의 하나로 객체의 상태 변화를 관찰하는 옵저버 목록을 객체에 등록해 상태 변화가 있을 때 마다 객체가 자신을 관찰하는 옵저버들에게 변화를 통지하는 디자인 패턴이다.

장점

  • 실시간으로 객체의 상태 변화를 전파할 수 있다.
  • 객체간의 의존성을 제거할 수 있다.

옵저버 패턴을 너무 많이 사용할 경우 상태 관리가 힘들 수 있음과 데이터 배분 문제를 고려해야한다.

구성

image

이미지 출처 : 위키피디아

  • Subject : 이벤트를 발생시키는 주체, 관찰의 대상인 객체
  • Observer : 관찰자, 관찰 대상인 객체가 발생시키는 이벤트를 처리

간단한 예시 (Kotlin)

옵저버 패턴은 보통 Listener의 형태로 이벤트 핸들링 시스템을 구현하는 데 사용된다. 우리는 간단하게 작동원리를 알 수 있는 예시를 작성해 보자.

우선 Observer의 인터페이스를 정의한다.

interface Observer {
    fun notify() : Boolean
}

이제 관리 대상이될 객체의 인터페이스를 정의하자

interface Subject {
    fun registerObserver(observer: Observer)
    fun unregisterObserver(observer: Observer)
    fun notifyObservers()
}

Observer 인터페이스를 상속받는 ObserverA와 ObserverB를 만든다.

class ObserverA : Observer {
    override fun notify() : Boolean{
        println("ObserverA action")
        return true
    }
}

class ObserverB : Observer {
    override fun notify(): Boolean {
        println("ObserverB action")
        return false
    }
}

딱히 별 기능은 없다. 옵저버에서 이벤트에 대한 처리가 일어남을 나타낸다.

이제 관찰의 대상이될 SubjectA 클래스를 만들어보자 앞서 만들었던 Subject의 인터페이스를 따른다.

class SubjectA : Subject {
    private val observerCollection = mutableListOf<Observer>()
    var num = 0

    override fun registerObserver(observer: Observer) {
        observerCollection.add(observer)
    }

    override fun unregisterObserver(observer: Observer) {
        observerCollection.remove(observer)
    }

    override fun notifyObservers() {
        observerCollection.forEach {
            it.notify()
        }
    }
}

notifyObservers()메소드를 호출 하는 것으로 해당 객체를 관찰하는 모든 Observer에게 이벤트를 통지할 수 있다. 물론 조건문 등을 이용해 특정 Observer에게만 이벤트를 통지하는 것도 가능하다.

다음 코드를 통해 Observer가 잘 작동하는지 확인해보자

fun main() {
    val subjectA = SubjectA()
    subjectA.registerObserver(ObserverA())
    subjectA.registerObserver(ObserverB())
    repeat(5){
        println("num : ${subjectA.num++}")
        subjectA.notifyObservers()
        println()
    }
}


출력

num : 0
ObserverA action
ObserverB action

num : 1
ObserverA action
ObserverB action

num : 2
ObserverA action
ObserverB action

num : 3
ObserverA action
ObserverB action

num : 4
ObserverA action
ObserverB action