python设计模式11:观察者模式

观察者模式

单个对此(发布者,也称为主体或是可观察对象)和一个或是多个对象(订阅者,也称为观察者)之间的发布-订阅关系。增加发布者和订阅这个之间解耦,使得在运行时添加、删除订阅者变得容易。对于MVC, 发布者是模型,订阅者是视图。

拍卖场景:

每个竞买人,都有一个号码牌,当天安门想要出价时,就举起号码牌。当竞买人举起牌子时,拍卖人即为主体,更新竞买价格,并将新价格广播给所有竞买人(竞买者)。

软件场景:

RabbitMQ 库可以用于应用程序添加异步消息支持,支持多种消息协议,http和amqp 。RbbitMQ 可以在Python 应用与发布订阅模式,该模式就是观察者设计模式。

新闻流:

使用RSS 、Atom 或其他相关格式。可以关注一个新闻流,每次更新时候,你都会收到一个关于更新的通知。

事件驱动系统

监听器监听特定的事件,监听器在监听的事件被创建时触发。这个事件可以是按下一个特定的键,移动鼠标,事件扮演发布者的角色,监听器扮演观察者的角色。可以为单个事件(发布者)添加多个监听器(观察者)。

案例

格式化程序,有一个默认的格式化程序,以十进制格式显示一个值,可以添加、注册更多的格式化程序。每次更新默认的格式化程序时候,都会通知已经注册的格式化程序采取行动。程序以相关格式显示新的值。

(1) 定义 Publisher 类。

(2) 定义 DefaultFormatter 类,以及特殊的 initstr 方法。

(3) 向 DefaultFormatter 类添加 data 属性的设置方法和获取方法。

(4) 定义两个观察者类

(5) 添加程序的主体部分。 main() 函数的第一部分如下。

复制代码
class Publisher:
    def __init__(self):
        self.observers = []  # 保存观察者

    def add(self, observer):
        if observer not in self.observers:
            self.observers.append(observer)
        else:
            print(f'Failed to add:{observer}')

    def remove(self, observer):
        try:
            self.observers.remove(observer)
        except ValueError:
            print(f"Failed to remove:{observer}")

    def notify(self):
        print("所有观察者通知更新")
        [o.notify(self) for o in self.observers]


class DefaultFormatter(Publisher):
    def __init__(self, name):
        Publisher.__init__(self)
        self.name = name
        self._data = 0

    def __str__(self):
        return f"{type(self).__name__}:'{self.name}' has data ={self._data}"

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, new_value):
        try:
            self._data = int(new_value)
        except ValueError as e:
            print(f"Error:{e}")
        else:
            self.notify()  # 执行通知
"""
定义两个观察者
"""

class HexFormatterObs:
    def notify(self, publisher):
        value = hex(publisher.data)
        print(f"{type(self).__name__}: '{publisher.data}' has now hex data ={value}")


class BinaryFormatterObs:
    def notify(self, publisher):
        value = bin(publisher.data)
        print(f"{type(self).__name__}:'{publisher.data}' has  now bin data ={value}")

def main():
    df=DefaultFormatter('test1')
    print(df)
    print("---------------------")
    hf=HexFormatterObs()
    df.add(hf)
    df.data=3
    print(df)
    bf=BinaryFormatterObs()
    df.add(bf)
    df.data=21
    print(df)
    print("----------hello-----------")
    df.data='hello'
    print(df)
    print("----------15.8-----------")
    df.data=15.8
    print(df)
if __name__ == '__main__':
    main()
    # try:
    #     print("33333")
    # except:
    #     print("wwww")
    # else:
    #     print("else")

执行结果

复制代码
DefaultFormatter:'test1' has data =0
---------------------
所有观察者通知更新
HexFormatterObs: '3' has now hex data =0x3
DefaultFormatter:'test1' has data =3
所有观察者通知更新
HexFormatterObs: '21' has now hex data =0x15
BinaryFormatterObs:'21' has  now bin data =0b10101
DefaultFormatter:'test1' has data =21
----------hello-----------
Error:invalid literal for int() with base 10: 'hello'
DefaultFormatter:'test1' has data =21
----------15.8-----------
所有观察者通知更新
HexFormatterObs: '15' has now hex data =0xf
BinaryFormatterObs:'15' has  now bin data =0b1111
DefaultFormatter:'test1' has data =15
相关推荐
wu~9702 小时前
手撕四种常用设计模式(工厂,策略,代理,单例)
java·单例模式·设计模式·代理模式·抽象工厂模式·策略模式
敲代码的 蜡笔小新8 小时前
【行为型之访问者模式】游戏开发实战——Unity灵活数据操作与跨系统交互的架构秘诀
unity·设计模式·c#·访问者模式
软考真题app1 天前
软件设计师考试结构型设计模式考点全解析
设计模式·软件设计师·结构型设计模式·考试考点
xiaolin03331 天前
【设计模式】- 行为型模式1
设计模式·状态模式·责任链模式·策略模式·命令模式·模板方法模式·行为型模式
沐土Arvin1 天前
深入理解 requestIdleCallback:浏览器空闲时段的性能优化利器
开发语言·前端·javascript·设计模式·html
bao_lanlan1 天前
兰亭妙微:用系统化思维重构智能座舱 UI 体验
ui·设计模式·信息可视化·人机交互·交互·ux·外观模式
总是难免1 天前
设计模式 - 单例模式 - Tips
java·单例模式·设计模式
Java致死1 天前
设计模式Java
java·开发语言·设计模式
ghost1432 天前
C#学习第23天:面向对象设计模式
开发语言·学习·设计模式·c#
敲代码的 蜡笔小新2 天前
【行为型之迭代器模式】游戏开发实战——Unity高效集合遍历与场景管理的架构精髓
unity·设计模式·c#·迭代器模式