Python筆記:觀察者模式

觀察者模式中的主題對象通常存在着一個其餘服務依賴的核心服務,而且維護着其餘依賴此核心服務的對象列表(即觀察者或監視者列表),當主題對象發生變化時,觀察者應該改變本身的狀態或者進行某些操做app

觀察者模式中的三個角色:spa

  • 主題:即觀察者觀察的對象,通常是須要有註冊和註銷方法,用來添加觀察者和刪除觀察者。
  • 觀察者基類:這個類主要是須要定義一個接口,以便主題發生變化時能夠獲得對應的通知信息。
  • 觀察者:這個類須要具體實現基類中的「通知」接口,以便和主題的變化保持同步。

主題的兩種通知方式:code

  • 拉模型:這個方式重心在觀察者上,當主題發生變化時,會廣播全部的觀察者,而後由觀察者來獲取相應的數據。
  • 推模型:這個方式重心在主題上,當主題發生變化時,主題將根據觀察者的須要將自身的變化推送給須要的觀察者。

觀察者模式的優勢:對象

  • 觀察者模式中彼此交互的對象都是保持鬆耦合的。主題對觀察者惟一的瞭解就是觀察者實現的「通知」接口,除此以外它們之間都是互不影響且獨立存在的,能夠根據須要對自身做出修改。
  • 能夠隨時添加或刪除觀察者。
  • 這種模式下,能夠在不多甚至不修改主題或觀察者的狀況下進行對象之間高效的數據發送。

其餘注意點:blog

  • 觀察者模式中是能夠有多個主題和多個觀察者之間的對應關係的,可是必定要弄清楚它們之間的關係以及變化,否則就會變得很是複雜。
  • 通常狀況是由主題來觸發「通知」方法的,可是在特殊狀況下也能夠由觀察者來觸發「通知」方法。

簡單示例:接口

from abc import ABCMeta, abstractmethod


class Publisher:
    """被觀察者:發佈/訂閱關係中的發佈對象"""
    def __init__(self):
        self.subscribers = []
        self.latest_content = None

    def set_content(self, content):
        """有新消息時,發佈新的消息"""
        self.latest_content = content
        self.publish()

    def get_latest_content(self):
        """獲取最新的消息"""
        return self.latest_content

    def register(self, subscriber):
        """註冊一個新的訂閱者"""
        self.subscribers.append(subscriber)

    def publish(self):
        """發佈消息並通知訂閱的用戶"""
        for subscriber in self.subscribers:
            subscriber.notify()


class Subscriber(metaclass=ABCMeta):
    """觀察者的抽象類:須要定義一個通知接口,用於發佈對象通知訂閱的用戶"""
    @abstractmethod
    def notify(self):
        pass


class SubscriberA(Subscriber):
    """觀察者A:發佈/訂閱關係中的訂閱者,當訂閱的發佈者有新的變化或動態的時候能及時收到通知"""
    def __init__(self):
        self.my_publisher = None

    def subscribe(self, publisher):
        """訂閱並進行註冊"""
        self.my_publisher = publisher
        self.my_publisher.register(self)

    def notify(self):
        """獲取最新消息"""
        latest_content = self.my_publisher.get_latest_content()
        print(self, latest_content)


class SubscriberB(Subscriber):
    """觀察者B:發佈/訂閱關係中的訂閱者,當訂閱的發佈者有新的變化或動態的時候能及時收到通知"""
    def __init__(self):
        self.my_publisher = None

    def subscribe(self, publisher):
        """訂閱並進行註冊"""
        self.my_publisher = publisher
        self.my_publisher.register(self)

    def notify(self):
        """獲取最新消息"""
        latest_content = self.my_publisher.get_latest_content()
        print(self, latest_content)


if __name__ == '__main__':
    new_publisher = Publisher()
    subscriber_a = SubscriberA()
    subscriber_a.subscribe(new_publisher)
    subscriber_b = SubscriberB()
    subscriber_b.subscribe(new_publisher)
    new_publisher.set_content('This is a new message!')
相關文章
相關標籤/搜索