python小白设计模式之观察者模式
要学好编程,或者说是软件开发,学好设计模式也是重要的一关(亲身体会!!!对于框架少的一些小众语言得自己去搭框架,不论开发还是维护,还是很费劲得),即便是有很多现成的框架可以使用,学好设计模式对框架优化或性能提升还是有帮助得。下面开始学习python下得观察者模式。虽然很懒,还是写点吧!本次学习的重点就是观察者模式的思想核心对像:被观察者接口、具体被观察者、观察者接口、具体观察者观察者:数据发布方法
python设计模式:观察者模式
前言
要学好编程,或者说是软件开发,学好设计模式也是重要的一关(亲身体会!!!对于框架少的一些小众语言得自己去搭框架,不论开发还是维护,还是很费劲得),即便是有很多现成的框架可以使用,学好设计模式对框架优化或性能提升还是有帮助得。下面开始学习python下得观察者模式。
一、观察者模式是什么?
观察者模式属于行为模式,核心包含观察者(Subject)、被观察者(Observer),用于一对多的场景,当要将数据发给多个目标时,通过被观察者,它会发送给所有观察者。
核心方法:
- 观察者:数据发布方法 update()
- 被观察者:
数据订阅方法 attach()
取消订阅方法 detach()
数据通知 notify()
由于数据的发布的对像可能不止一个、数据的观察者(关注者)的对像也不同,因此观察者模式也比设计为:被观察者接口(SubjectInterface)、具体观察者对像(Subject)、观察者接口(ObserverInterface)、具体观察者(Observer)。
一个典型的应用就是发布-订阅模型。
二、Python中观察者模式实现
1.引入库
在Python里面设计接口用到abc(abstract base classes,ABCs)模块,用到元类ABCMeta和abstractmethod方法,继承抽象类的对像必须实现abstractmethod装饰的方法。
from abc import ABCMeta, abstractmethod
class Interface(metaclass=ABCMeta):
@abstractmethod
def func(self):
pass
class ConcreateInterface(Interface):
def func(self):
print("实现接口方法")
2.观察者模式在python实现
(1)观察者接口
from abc import ABCMeta, abstractmethod
# 观察者接口
class ObserverInterface(metaclass=ABCMeta):
@abstractmethod
def update(self, subject, message):
pass
(2)观察对像
# 观察对像
class SubjectInterface:
@abstractmethod
def attach(self, observer):
pass
@abstractmethod
def detach(self, observer):
pass
@abstractmethod
def notify(self, message):
pass
(3)具体被观察对像
class ConcreateSubject(SubjectInterface):
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self, message):
for observer in self._observers:
observer.update(self, message)
def get_observers(self):
return self._observers
(4)具体观察者
# 观察者
class ConcreateObserver(ObserverInterface):
def update(self, subject, message):
print(f"接收到主题{subject}的通知:{message}")
(5)实例化
if __name__ == "__main__":
subject = ConcreateSubject()
observer1 = ConcreateObserver()
observer2 = ConcreateObserver()
subject.attach(observer1)
subject.attach(observer2)
subject.notify("test")
打印结果
接收到主题<__main__.ConcreateSubject object at 0x0000021EA31280A0>的通知:tetst
接收到主题<__main__.ConcreateSubject object at 0x0000021EA31280A0>的通知:tetst
三、发布-订阅模式
直接上代码:
from abc import abstractmethod, ABCMeta
class PublishInterface(metaclass=ABCMeta):
@abstractmethod
def update(self, message):
pass
# 订阅主题
class Subject:
def __init__(self):
self._subscribers = []
# 订阅
def subscribe(self, subscriber):
self._subscribers.append(subscriber)
# 取消订阅
def unsubscribe(self, observer):
self._subscribers.remove(observer)
def publish(self, message):
for subscriber in self._subscribers:
subscriber.update(message)
def get_subscribers(self):
return self._subscribers
# 观察者
class Subscriber(PublishInterface):
def update(self, message):
print(f"接收到主题的通知:{message}")
class Server:
def __init__(self):
super().__init__()
self.users = {} # 模拟用户信息存储
self.subjects = {} # 主题管理
def user_register(self, customer):
user = customer.username
if user not in self.users.keys():
self.users[customer.username] = customer.pwd
def user_unregister(self, username):
self.users.pop(username)
def subscribe_with_subject(self, customer, subject=''):
user = customer.username
if user in self.users.keys():
# 不存在则创建主题
if subject in self.subjects:
self.subjects.get(subject).subscribe(customer)
# 否则直接添加
else:
subject_ = Subject()
subject_.subscribe(customer)
self.subjects[subject] = subject_
else:
print("请先注册!!!")
def unsubscribe_with_subject(self, customer, subject=''):
self.subjects.get(subject).unsubscribe(customer)
def print_subjects_info(self):
print("\n***************订阅管理信息表*************************")
for subject, subject_obj in self.subjects.items():
print(f"{subject}:")
for subscriber in subject_obj.get_subscribers():
print(f"\t{subscriber.username}")
def print_subjects_by_user(self, user):
print("\n***************用户订阅信息表*************************")
print(f"{user}:")
for subject, subject_obj in self.subjects.items():
for subscriber in subject_obj.get_subscribers():
if user == subscriber.username:
print(f"\t{subject}")
def sports_notify(self):
print("**********************发布体育讯息*********************")
self.subjects.get("体育").publish("发布了一条体育讯息!\n")
def technology_notify(self):
print("**********************发布科技报道*********************")
self.subjects.get("科技").publish("发布了一条科技报道!\n")
class Customer(Subscriber):
def __init__(self, username, pwd):
super().__init__()
self.username = username
self.pwd = pwd
def update(self, message):
print(f"****************<{self.username}>:接受订阅信息********")
print(f"我是用户:{self.username},接收到订阅消息:{message}\n")
if __name__ == "__main__":
server = Server()
customer1 = Customer("Lily", "tets123")
customer2 = Customer("Aobama", "tets00123")
server.subscribe_with_subject(customer1, "体育")
server.subscribe_with_subject(customer1, "科技")
server.subscribe_with_subject(customer2, "科技")
server.user_register(customer1)
server.user_register(customer2)
server.subscribe_with_subject(customer1, "体育")
server.subscribe_with_subject(customer1, "科技")
server.subscribe_with_subject(customer2, "科技")
server.print_subjects_info()
server.print_subjects_by_user(customer1.username)
server.unsubscribe__with_subject(customer1, "科技")
server.print_subjects_info()
server.print_subjects_by_user(customer1.username)
server.sports_notify()
server.technology_notify()
打印结果:
请先注册!!!
请先注册!!!
请先注册!!!
***************订阅管理信息表*************************
体育:
Lily
科技:
Lily
Aobama
***************用户订阅信息表*************************
Lily:
体育
科技
***************订阅管理信息表*************************
体育:
Lily
科技:
Aobama
***************用户订阅信息表*************************
Lily:
体育
**********************发布体育讯息*********************
****************<Lily>:接受订阅信息********
我是用户:Lily,接收到订阅消息:发布了一条体育讯息!
**********************发布科技报道*********************
****************<Aobama>:接受订阅信息********
我是用户:Aobama,接收到订阅消息:发布了一条科技报道!
总结
虽然很懒,还是写点吧!
- 本次学习的重点就是观察者模式的思想核心
对像:被观察者接口、具体被观察者、观察者接口、具体观察者
观察者:数据发布方法 update()
被观察者:
数据订阅方法 attach()
取消订阅方法 detach()
数据通知 notify()
- 以及python里面接口的定义:ACBMeta元类、abstractmethod方法。
更多推荐
所有评论(0)