본문 바로가기

Programming/Design pattern

[Design pattern] Observer pattern

Observer Pattern

Observer Pattern

상태를 가지고 있는 주체 객체상태의 변경을 알아야 하는 관찰 객체(Observer Object)가 존재하며 이들의 관계는 1:1이 될 수도 있고 1:N이 될 수가 있다.

서로의 정보를 넘기고 받는 과정에서 정보의 단위가 클 수록, 객체들의 규모다 클 수록, 각 객체들의 관계가 복잡할 수록 점점 구현하기 어려워지고 복잡성이 매우 증가할 것이다. 이러한 기능을 할 수 있도록 가이드라인을 제시해 주는 것이 바로 옵저버 패턴이다.

  • 옵저버 패턴은 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들에게 연락이 가고 자동으로 정보가 갱신되는 1:N 의 관계를 정의한다.
  • 연결은 인터페이스를 이용하여 느슨한 결합성을 유지한다. 주체, 옵저버 인터페이스를 적용한다.
  • 옵저버 패턴은 푸시 방식과 풀 방식으로 언제든지 구현할 수 있다.
  • JAVA에서 기본으로 Observable 클래스와 Observer 인터페이스를 제공한다.
  • Swing, Android 등 UI와 관련된 곳에서 이 옵저버 패턴이 많이 사용된다. (물론 이보다 더 많다)

참고 : 디자인패턴 - 옵저버 패턴(Observer Pattern), 디자인패턴 - 옵저버 패턴 (observer pattern)




Android Example

요구사항 : +, - 버튼을 누르면 TextView의 내용을 변경. 추가적으로 add 버튼을 누르면 옵저버를 attach하고, delete 버튼을 누르면 detach 한다.

각 클래스를 정의할 때 중요한 것은 import 가 있으면 안된다 (다른 클래스와 결합되어있으면 안된다) -> 객체지향적으로 설계하자!

Publisher 클래스

open class Publisher<T>(defaultValue: T) {
    private val observers = ArrayList<Observer<T>>() // 이 클래스를 구독하고 있는 옵저버 리스트
    private var value: T = defaultValue
    var allowInit = true // 퍼블리셔의 상태를 최신으로 유지할지 여부(옵저버가 detach 된 상태에서는 갱신되지 않는다.)

    fun add(observer: Observer<T>) {
        if (!observers.contains(observer)) {
            observers.add(observer)
            if (allowInit) observer.update(value)
        }
    }

    fun delete(observer: Observer<T>) {
        observers.remove(observer)
    }

    protected fun setValue(value: T) {
        this.value = value
        notifyObserver()
    }

    protected fun getValue(): T = value

    private fun notifyObserver() {
        observers.forEach { it.update(value) }
    }
}

Publisher 클래스를 상속한 MyPublisher

class MyPublisher : Publisher<Int>(0) {
    fun increase() {
        setValue(getValue() + 1)
    }

    fun decrease() {
        setValue(getValue() - 1)
    }
}

MainActivity

class MainActivity : AppCompatActivity(), Observer<Int> {
    private val publisher = MyPublisher()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        publisher.allowInit = false

        btn_plus.setOnClickListener {
            publisher.increase()
        }

        btn_minus.setOnClickListener {
            publisher.decrease()
        }

        btn_add.setOnClickListener {
            publisher.add(this)
        }

        btn_delete.setOnClickListener {
            publisher.delete(this)
        }
    }

    override fun update(value: Int) {
        textView.text = value.toString()
    }
}

 

'Programming > Design pattern' 카테고리의 다른 글

[Design pattern] Factory method pattern  (0) 2021.07.05
[Design pattern] Adapter pattern  (0) 2019.01.02
[Design pattern] Singleton pattern  (0) 2019.01.02
[Design pattern] Builder pattern  (0) 2019.01.02