doc.dev1x.org

Observerパターン

1. 目的

状態の変化時、関連するオブジェクトに状態変更を通知する機構が欲しい

2. 課題

機構として提供したいので通知対象のオブジェクトは任意に追加・削除したい

3. 解決策

通知を受けて処理を行うオブジェクトを定義する

class Subscriber:
    def __init__(self, msg):
        self.__msg = msg

    def update(self):
        print(self.__msg)

通知を受けるオブジェクトを集約するオブジェクトを定義する

class Publisher:
    def __init__(self):
        self.__subscribers = []

    def register(self, subscriber):
        self.__subscribers.append(subscriber)

    def unregister(self, subscriber):
        self.__subscribers.remove(subscriber)

    def notify(self):
        for subscriber in self.__subscribers:
            subscriber.update()

使い方

pub = Publisher()

sub1 = Subscriber("わーい")
sub2 = Subscriber("うぇーい")

pub.register(sub1)
pub.register(sub2)

pub.notify()    # => わーい うぇーい

pub.unregister(sub2)

pub.notify()    # => わーい

4. メリット

通知を受けて処理を行うオブジェクトを自由に増やすことができる

通知を受けるクラスの責務が単純になる

5. デメリット

構成要素が増えるので複雑性が増加する

6. 注意事項

アプリケーションロジックの中で利用する機会は少ない

Appendix-1 サンプルコード

class Publisher:
    def __init__(self):
        self.__subscribers = []

    def register(self, subscriber):
        self.__subscribers.append(subscriber)

    def unregister(self, subscriber):
        self.__subscribers.remove(subscriber)

    def notify(self):
        for subscriber in self.__subscribers:
            subscriber.update()

class Subscriber:
    def __init__(self, msg):
        self.__msg = msg

    def update(self):
        print(self.__msg)


if __name__ == '__main__':
    pub = Publisher()

    sub1 = Subscriber("わーい")
    sub2 = Subscriber("うぇーい")
    pub.register(sub1)
    pub.register(sub2)

    pub.notify()    # => わーい うぇーい

    pub.unregister(sub2)

    pub.notify()    # => わーい