Python

Python デザインパターンを学ぶ Observerパターン

概要

Observerパターンは、オブジェクト(observable)とその依存関係(observers)の間の一対多の依存関係をモデル化するために使用できる。このパターンでは、observableは、関連する状態の変化をすべてのobserversに通知する責任がある。このパターンは、中央の状態が非中央の動作に影響を与える場合(分散イベント処理など)に特に有効だ。

以下の実行例では、あるフォーラム(observable、ステートフルな実体)を、複数の自然言語処理ボット(observers)が観測している様子をシミュレーションする。フォーラムに新しいポストが追加されると、ボットに通知される。各ボットは、新しい投稿を処理し、責任を果たす(処理イベントの実装は、このデモの範囲を超えているため、省略する)。

実装例

すべてのオブザーバーボットは、AbstractObserverBotクラスを継承する。すべてのボットは、新しい投稿を通知するためにフォーラムが呼び出すプロセスメソッドを共有しており、このイベントの処理に関しては、それぞれの子が独自の責任を負う。

class ObservableForum:

    def __init__(self):
        self._observer_bots = []

    def add_observer_bot(self, new_bot):

        if not any(isinstance(bot, new_bot.__class__) for bot in
                   self._observer_bots):
            print("Add observer: {}".format(new_bot.__class__.__name__))
            self._observer_bots.append(new_bot)

    def remove_observer_bot(self, bot_to_remove):

        for bot in self._observer_bots:
            if isinstance(bot, bot_to_remove.__class__):
                print("Remove observer: {}".format(bot.__class__.__name__))
                self._observer_bots.remove(bot)
                return None

    def new_post(self, post):
        self._notify_observers(post)
        pass

    def _notify_observers(self, post):

        for bot in self._observer_bots:
            bot.process(post)


class AbstractObserverBot():

    def process(self, post):
        print("> {} is processing new post".format(self.__class__.__name__))


class SentimentAnalyser(AbstractObserverBot):
    pass


class SpamDetector(AbstractObserverBot):
    pass


if __name__ == "__main__":

    sa_bot = SentimentAnalyser()
    sd_bot = SpamDetector()
    forum = ObservableForum()

    forum.add_observer_bot(sa_bot)
    forum.add_observer_bot(sd_bot)
    print("\n")

    forum.new_post("sample post")

    forum.remove_observer_bot(sd_bot)

    forum.new_post("sample post2")