【Gang of Four】デザインパターン学習 - Observer


Observer - 観察者

目次
あるオブジェクトのプロパティが更新されたときに、それを監視している他のオブジェクトに同時になにか処理をさせようというのが本パターンです。

更新されたオブジェクトが監視しているオブジェクトに更新されたことを通知するようなイメージですね。
Android Architecture ComponentsのLiveDataがまさにこれ。

目的

あるオブジェクトが状態を変えたときに、それに依存するすべてのオブジェクトに自動的にそのことが知らされ、また、それらが更新されるように、オブジェクト間に一対多の依存関係を定義する。

構成要素

・Subject 監視される抽象クラス
・Observer 監視したい抽象クラス
・ConcreteSubject 監視される具象クラス
・ConcreteObserver 監視したい具象クラス

実装

スマホにインストールしているアプリがアップデートされると、自動で更新されるサンプルプログラムを実装します。
play storeがsubjectでスマホがobserverですね。
めんどくさいので抽象クラスは実装しません。

ConcreteSubject 監視される具象クラス

play storeです。

PlayStore.kt
package observer

class PlayStore {
    interface UpdateListener {
        fun update(latestVersion: Int)
    }

    private val listeners = ArrayList<UpdateListener>()

    fun update(latestVersion: Int) {
        println("サンプルアプリが${latestVersion}にアップデートされました。")
        listeners.forEach {
            it.update(latestVersion)
        }
    }

    fun addListener(listener: UpdateListener) {
        listeners.add(listener)
    }
}

ConcreteObserver 監視したい具象クラス

本パターンの効果が実感しやすいように、observeするクラスを2つ実装します。

サンプルアプリをインストールしているユーザ一人目

SnakeSmartPhone.kt
package observer

class SnakeSmartPhone(playStore: PlayStore) {
    init {
        playStore.addListener(object: PlayStore.UpdateListener {
            override fun update(latestVersion: Int) {
                println("スネークのスマホのアプリが${latestVersion}にサンプルアップデートされました。")
            }
        })
    }
}

サンプルアプリをインストールしているユーザ二人目

Raiden.kt
package observer

class RaidenSmartPhone(playStore: PlayStore) {
    init {
        playStore.addListener(object: PlayStore.UpdateListener {
            override fun update(latestVersion: Int) {
                println("雷電のスマホのサンプルアプリが${latestVersion}にアップデートされました。")
            }
        })
    }
}

使う人

Client.kt
package observer

class Client {
    init {
        val playStore = PlayStore()
        SnakeSmartPhone(playStore)
        RaidenSmartPhone(playStore)

        playStore.update(1)

        playStore.update(2)
    }
}

出力結果

[out-put]
サンプルアプリが1にアップデートされました。
スネークのスマホのサンプルアプリが1にアップデートされました。
雷電のスマホのサンプルアプリが1にアップデートされました。
サンプルアプリが2にアップデートされました。
スネークのスマホのサンプルアプリが2にアップデートされました。
雷電のスマホのサンプルアプリが2にアップデートされました。

play storeのアプリをアップデートするたび、それをインストールしているスマホも自動でアップデートされています。

以上