您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

python设计模式之观察者模式

5b51 2022/1/14 8:24:16 python 字数 34589 阅读 593 来源 www.jb51.cc/python

一.行为型模式 创建型模式基于对象的创建机制,隔离了对象的创建细节,使代码能够与要创建的对象的类型相互独立 结构型模式用于设计对象和类的结构,使它们可以相互协作以获得更大的结构 行为型模式主要关注对象

概述

<div class="markdown-here-wrapper" data-md-url="https://i.cnblogs.com/EditPosts.aspx?opt=1"&gt;
<h1 id="-" style="margin: 20px 0px 10px; padding: 0px; font-weight: bold; color: black; font-size: 24px; border-bottom: 2px solid #aaaaaa;">一.行为型模式
<blockquote style="margin: 1.2em 0px; border-left: 4px solid #dddddd; padding: 0px 1em; color: #777777; quotes: none;">
<ul style="margin: 1.2em 0px; padding-left: 2em; list-style-type: square; font-size: 16px;">
<li style="margin: 0.5em 0px; font-size: 16px;">
<p style="margin: 0.5em 0px !important; font-size: 16px; line-height: 1.75em; padding-right: 0.5em; padding-left: 0.5em;">创建型模式基于对象的创建机制,隔离了对象的创建细节,使代码能够与要创建的对象的类型相互独立

主题维护了一个依赖(观察者)列表,以便主题可以使用观察者定义的任何方法通知所有观察者它所发生的变化。

一个接口,里边定义了观察者获得通知方法,ConcreteObserver(具体观察者)实现这些接口,并与主题创建相关联系,Subject主题存储所有注册的观察者,并向所有观察者发送新消息。

主题对象的新消息,当主题对象有了新消息的时候,它就会通知所有的观察着它的对象,就像是很多的用户订阅了一位新闻发布者,当新闻发布者发布了一个新的新闻后,他就会通知它的所有订阅者,就像是手机上一些应用的通知栏通知

通知方式,拉模型和推模型

 abc  ABCMeta,abstractmethod

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">NewsPublisher: <span class="hljs-comment" style="color: #7285b7;">#subject
<span class="hljs-function" style="color: #bbdaff;"><span class="hljs-keyword" style="color: #ebbbff;">def <span class="hljs-title" style="color: #7285b7;">init<span class="hljs-params" style="color: #ffc58f;">(self):
self.subscribers = []
self.
latestNews = <span class="hljs-keyword" style="color: #ebbbff;">None

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;attach</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self,subscriber)</span>:</span>
    self.__subscribers.append(subscriber)

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;detach</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;return</span> self.__subscribers.pop()

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;notifySubscribers</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;for</span> sub <span class="hljs-keyword" style="color: #ebbbff;"&gt;in</span> self.__subscribers:
        sub.update()

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;addNews</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self,news)</span>:</span>
    self.__latestNews = news

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;getNews</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;return</span> <span class="hljs-string" style="color: #d1f1a9;"&gt;'Got News:'</span>+self.__latestNews

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">Subscriber<span class="hljs-params" style="color: #ffc58f;">(Metaclass=ABCMeta): <span class="hljs-comment" style="color: #7285b7;">#Observer

<span class="hljs-decorator"&gt;@abstractmethod</span>
<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;update</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;pass</span>

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">ConcreteSubscriber1: <span class="hljs-comment" style="color: #7285b7;">#ConcreteObserver
<span class="hljs-function" style="color: #bbdaff;"><span class="hljs-keyword" style="color: #ebbbff;">def <span class="hljs-title" style="color: #7285b7;">init<span class="hljs-params" style="color: #ffc58f;">(self,publisher):
self.publisher=publisher
self.publisher.attach(self)

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;update</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    print(type(self).<a href="https://www.jb51.cc/tag/name/" target="_blank" class="keywords">__name__</a>,self.publisher.getNews())

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">ConcreteSubscriber2:
<span class="hljs-function" style="color: #bbdaff;"><span class="hljs-keyword" style="color: #ebbbff;">def <span class="hljs-title" style="color: #7285b7;">init<span class="hljs-params" style="color: #ffc58f;">(self,publisher):
self.publisher = publisher
self.publisher.attach(self)

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;update</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    print(type(self).<a href="https://www.jb51.cc/tag/name/" target="_blank" class="keywords">__name__</a>,self.publisher.getNews())

news_publisher = NewsPublisher()
<span class="hljs-keyword" style="color: #ebbbff;">for Subscribers <span class="hljs-keyword" style="color: #ebbbff;">in [ConcreteSubscriber1,ConcreteSubscriber2]: <span class="hljs-comment" style="color: #7285b7;">#创建观察者对象
Subscribers(news_publisher)

news_publisher.addNews(<span class="hljs-string" style="color: #d1f1a9;">'HELLO WORLD')
news_publisher.notifySubscribers()
news_publisher.detach()
news_publisher.addNews(<span class="hljs-string" style="color: #d1f1a9;">'SECOND NEWS')
news_publisher.notifySubscribers()
<span class="hljs-string" style="color: #d1f1a9;">'''
ConcreteSubscriber1 Got News:HELLO WORLD
ConcreteSubscriber2 Got News:HELLO WORLD
ConcreteSubscriber1 Got News:SECOND NEWS
'''

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;attach</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self,subscriber)</span>:</span>
    self.__subscribers.append(subscriber)

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;detach</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;return</span> self.__subscribers.pop()

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;notifySubscribers</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;for</span> sub <span class="hljs-keyword" style="color: #ebbbff;"&gt;in</span> self.__subscribers:
        sub.update()

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;addNews</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self,news)</span>:</span>
    self.__latestNews = news

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;getNews</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;return</span> <span class="hljs-string" style="color: #d1f1a9;"&gt;'Got News:'</span>+self.__latestNews
<span class="hljs-decorator"&gt;@abstractmethod</span>
<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;update</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;pass</span>
<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;update</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    print(type(self).<a href="https://www.jb51.cc/tag/name/" target="_blank" class="keywords">__name__</a>,self.publisher.getNews())
<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;update</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    print(type(self).<a href="https://www.jb51.cc/tag/name/" target="_blank" class="keywords">__name__</a>,self.publisher.getNews())

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">NewsPublisher: <span class="hljs-comment" style="color: #7285b7;">#subject
<span class="hljs-function" style="color: #bbdaff;"><span class="hljs-keyword" style="color: #ebbbff;">def <span class="hljs-title" style="color: #7285b7;">init<span class="hljs-params" style="color: #ffc58f;">(self):
self.subscribers = []
self.
latestNews = <span class="hljs-keyword" style="color: #ebbbff;">None

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">Subscriber<span class="hljs-params" style="color: #ffc58f;">(Metaclass=ABCMeta): <span class="hljs-comment" style="color: #7285b7;">#Observer

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">ConcreteSubscriber1: <span class="hljs-comment" style="color: #7285b7;">#ConcreteObserver
<span class="hljs-function" style="color: #bbdaff;"><span class="hljs-keyword" style="color: #ebbbff;">def <span class="hljs-title" style="color: #7285b7;">init<span class="hljs-params" style="color: #ffc58f;">(self,publisher):
self.publisher=publisher
self.publisher.attach(self)

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">ConcreteSubscriber2:
<span class="hljs-function" style="color: #bbdaff;"><span class="hljs-keyword" style="color: #ebbbff;">def <span class="hljs-title" style="color: #7285b7;">init<span class="hljs-params" style="color: #ffc58f;">(self,publisher):
self.publisher = publisher
self.publisher.attach(self)

news_publisher = NewsPublisher()
<span class="hljs-keyword" style="color: #ebbbff;">for Subscribers <span class="hljs-keyword" style="color: #ebbbff;">in [ConcreteSubscriber1,ConcreteSubscriber2]: <span class="hljs-comment" style="color: #7285b7;">#创建观察者对象
Subscribers(news_publisher)

news_publisher.addNews(<span class="hljs-string" style="color: #d1f1a9;">'HELLO WORLD')
news_publisher.notifySubscribers()
news_publisher.detach()
news_publisher.addNews(<span class="hljs-string" style="color: #d1f1a9;">'SECOND NEWS')
news_publisher.notifySubscribers()
<span class="hljs-string" style="color: #d1f1a9;">'''
ConcreteSubscriber1 Got News:HELLO WORLD
ConcreteSubscriber2 Got News:HELLO WORLD
ConcreteSubscriber1 Got News:SECOND NEWS
'''

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">NewsPublisher: <span class="hljs-comment" style="color: #7285b7;">#subject
<span class="hljs-function" style="color: #bbdaff;"><span class="hljs-keyword" style="color: #ebbbff;">def <span class="hljs-title" style="color: #7285b7;">init<span class="hljs-params" style="color: #ffc58f;">(self):
self.subscribers = []
self.
latestNews = <span class="hljs-keyword" style="color: #ebbbff;">None

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;attach</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self,subscriber)</span>:</span>
    self.__subscribers.append(subscriber)

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;detach</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;return</span> self.__subscribers.pop()

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;notifySubscribers</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;for</span> sub <span class="hljs-keyword" style="color: #ebbbff;"&gt;in</span> self.__subscribers:
        sub.update()

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;addNews</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self,news)</span>:</span>
    self.__latestNews = news

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;getNews</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;return</span> <span class="hljs-string" style="color: #d1f1a9;"&gt;'Got News:'</span>+self.__latestNews

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">Subscriber<span class="hljs-params" style="color: #ffc58f;">(Metaclass=ABCMeta): <span class="hljs-comment" style="color: #7285b7;">#Observer

<span class="hljs-decorator"&gt;@abstractmethod</span>
<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;update</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    <span class="hljs-keyword" style="color: #ebbbff;"&gt;pass</span>

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">ConcreteSubscriber1: <span class="hljs-comment" style="color: #7285b7;">#ConcreteObserver
<span class="hljs-function" style="color: #bbdaff;"><span class="hljs-keyword" style="color: #ebbbff;">def <span class="hljs-title" style="color: #7285b7;">init<span class="hljs-params" style="color: #ffc58f;">(self,publisher):
self.publisher=publisher
self.publisher.attach(self)

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;update</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    print(type(self).<a href="https://www.jb51.cc/tag/name/" target="_blank" class="keywords">__name__</a>,self.publisher.getNews())

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">ConcreteSubscriber2:
<span class="hljs-function" style="color: #bbdaff;"><span class="hljs-keyword" style="color: #ebbbff;">def <span class="hljs-title" style="color: #7285b7;">init<span class="hljs-params" style="color: #ffc58f;">(self,publisher):
self.publisher = publisher
self.publisher.attach(self)

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;update</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self)</span>:</span>
    print(type(self).<a href="https://www.jb51.cc/tag/name/" target="_blank" class="keywords">__name__</a>,self.publisher.getNews())

news_publisher = NewsPublisher()
<span class="hljs-keyword" style="color: #ebbbff;">for Subscribers <span class="hljs-keyword" style="color: #ebbbff;">in [ConcreteSubscriber1,ConcreteSubscriber2]: <span class="hljs-comment" style="color: #7285b7;">#创建观察者对象
Subscribers(news_publisher)

news_publisher.addNews(<span class="hljs-string" style="color: #d1f1a9;">'HELLO WORLD')
news_publisher.notifySubscribers()
news_publisher.detach()
news_publisher.addNews(<span class="hljs-string" style="color: #d1f1a9;">'SECOND NEWS')
news_publisher.notifySubscribers()
<span class="hljs-string" style="color: #d1f1a9;">'''
ConcreteSubscriber1 Got News:HELLO WORLD
ConcreteSubscriber2 Got News:HELLO WORLD
ConcreteSubscriber1 Got News:SECOND NEWS
'''

代码中,主题通知观察者步骤即为news_publisher.notifySubscribers()中调用所有观察者的update方法,这里的update方法没有参数,观察者从主题那里提取数据步骤即为具体观察者的update方法中又调用self.publisher.getNews()来获得数据

主题直接发送信息到观察者,代码只需将拉模型的稍微改动即可:

<span class="hljs-class"><span class="hljs-keyword" style="color: #ebbbff;">class <span class="hljs-title" style="color: #7285b7;">ConcreteSubscriber2:
<span class="hljs-function" style="color: #bbdaff;"><span class="hljs-keyword" style="color: #ebbbff;">def <span class="hljs-title" style="color: #7285b7;">init<span class="hljs-params" style="color: #ffc58f;">(self,publisher):
self.publisher = publisher
self.publisher.attach(self)

<span class="hljs-function" style="color: #bbdaff;"&gt;<span class="hljs-keyword" style="color: #ebbbff;"&gt;def</span> <span class="hljs-title" style="color: #7285b7;"&gt;update</span><span class="hljs-params" style="color: #ffc58f;"&gt;(self,news)

news_publisher = NewsPublisher()
<span class="hljs-keyword" style="color: #ebbbff;">for Subscribers <span class="hljs-keyword" style="color: #ebbbff;">in [ConcreteSubscriber1,ConcreteSubscriber2]: <span class="hljs-comment" style="color: #7285b7;">#创建观察者对象
Subscribers(news_publisher)

news_publisher.addNews(<span class="hljs-string" style="color: #d1f1a9;">'HELLO WORLD')
news_publisher.notifySubscribers()
news_publisher.detach()
news_publisher.addNews(<span class="hljs-string" style="color: #d1f1a9;">'SECOND NEWS')
news_publisher.notifySubscribers()

<span class="hljs-string" style="color: #d1f1a9;">'''
ConcreteSubscriber1 HELLO WORLD
ConcreteSubscriber2 HELLO WORLD
ConcreteSubscriber1 SECOND NEWS
'''

<p style="margin: 0px 0px 1.2em !important; font-size: 16px; line-height: 1.75em; padding-right: 0.5em; padding-left: 0.5em;">这里只将update函数添加了传递的数据参数,并在notifySubscribers函数中传递了参数。


如果您也喜欢它,动动您的小指点个赞吧

除非注明,文章均由 laddyq.com 整理发布,欢迎转载。

转载请注明:
链接:http://laddyq.com
来源:laddyq.com
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


联系我
置顶