【观察者设计模式详解】C/Java/JS/Go/Python/TS不同语言实现-消息
(资料图片)
简介观察者模式(Observer Pattern)是一种行为型模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
观察者模式使用三个类Subject、Observer和Client。Subject对象带有绑定观察者到Client对象和从Client对象解绑观察者的方法。我们创建Subject类、Observer抽象类和扩展了抽象类Observer的实体类。
作用一个对象状态更新,其他依赖对象收到通知和自动更新的机制。实现模块化分离,实现主题与观察者交互对象之间的松耦合。1)观察者定义了对象之间一对多的关系。2)被观察者(主题)用一个共同的接口来更新观察者。3)观察者和被观察者用松耦合方式结合,被观察者不知道观察者的细节,只知道观察者实现了观察者接口。实现步骤创建观察者observer基础接口,包含主题和更新方法创建主题subject抽象类,包含observer列表以及添加和删除方法创建具体的主题类,实现通知方法,发布通知时轮询通知全部观察者创建多个具体观察者,与主题关联,并实现自己的更新方法客户调用时先声明主题,再将观察者分别添加到主题,当主题发布通知时,观察者自动更新UMLJava代码观察者接口// ObserverAPI.java 观察者接口,Java 9已经默认支持Observer接口// 这里避免冲突采取ObserverAPI命名public interface ObserverAPI { public Subject subject = null; public void update(String content);}
具体观察者// ConcreteObserver.java 具体的观察者实现类,也可以看成订阅者,关联对应的主题类。// 不同的观察者也可以对应多个主题public class ConcreteObserver implements ObserverAPI { public Subject subject; // 给观察者绑定主题,同时把观察者添加到主题列表 public ConcreteObserver(Subject subject) { this.subject = subject; this.subject.register((ObserverAPI) this); } // 观察者发出更新通知,不用单独告诉订阅者,由订阅者自行监听 public void update(String content) { System.out.println(String.format("%s::update() [subject.name = %s content = %s]", this.getClass().getName(), this.subject.getName(), content)); }}
// ConcreteObserver2.java 具体的观察者实现类,也可以看成订阅者,关联对应的主题类。// 不同的观察者可以对应不同的主题。public class ConcreteObserver2 implements ObserverAPI { // 这里没有在构造器就绑定某个主题,而是从客户角度去注册观察者 public ConcreteObserver2() { } // 观察者发出更新通知,观察者自行监听 public void update(String content) { System.out.println(String.format("%s::update() [content = %s]", this.getClass().getName(), content)); }}
抽象主题类// Subject.java 定义抽象主题类或者接口,供具体主题类继承public abstract class Subject { private String name; // protected Set observers = new HashSet<>(); protected List observers = new ArrayList<>(); public String getName() { return name; } public void setName(String name) { this.name = name; } public void register(ObserverAPI observer) { System.out.println(this.getClass().getName() + "::register() [observer = " + observer.getClass().getSimpleName() + "]"); observers.add(observer); } public void remove(ObserverAPI observer) { observers.remove(observer); } // 通知由具体类来实现逻辑 public abstract void notify(String name);}
具体主题类// ConcreteSubject.java 观察者主题类,也是发布者,重写具体的通知方法。不同主题可以关联不同的观察者。public class ConcreteSubject extends Subject { public ConcreteSubject(String name) { this.setName(name); } // 不同的主题类有自己的通知方法,批量通知绑定的观察者 @Override public void notify(String content) { System.out.println(this.getClass().getName() + "::notify() [content = " + content + "]"); for (Object observer : this.observers) { ((ObserverAPI) observer).update(content); } }}
测试调用/** * 观察者模式应用非常广泛,主要是观察者提前绑定到发布者 * 当发布者发布消息时,批量广播通知,而无需逐一通知 * 观察者监听到消息后自己决定采取哪一种行为 */ // 定义一个主题,也就是发布者 Subject concreteSubject = new ConcreteSubject("subject1"); // 再声明观察者,通过构造器注册到主题上 ObserverAPI observer1 = new ConcreteObserver(concreteSubject); // 也可以单独给主题注册一个新的观察者 concreteSubject.register(new ConcreteObserver2()); // 可以移除观察者对象,可以打开注释试下 // concreteSubject.remove(observer1); // 主题开始发布新通知,各观察者自动更新 concreteSubject.notify("hello, this is broadcast.");
Python代码观察者接口# ObserverAPI.py 观察者抽象父类,定义一些公共方法class ObserverAPI: def __init__(self, name): self.name = name # 观察者发出更新通知,观察者自行监听 def update(self, content): print(self.__class__.__name__ + "::update() [content = " + content + "]") def set_name(self, name): self.name = name
具体观察者# ConcreteObserver.py 具体的观察者实现类,也可以看成订阅者,关联对应的主题类。# 不同的观察者也可以对应多个主题from src.ObserverAPI import ObserverAPI# 具体的观察者实现类,也可以看成订阅者,关联对应的主题类。# 不同的观察者也可以对应多个主题class ConcreteObserver(ObserverAPI): # 给观察者绑定主题,同时把观察者添加到主题列表 def __init__(self, subject, name): ObserverAPI.__init__(self, name) # python3支持的父类调用 # super(ConcreteObserver, self).__init__(name) # super().__init__(name) self.subject = subject subject.register(self) # 观察者发出更新通知,不用单独告诉订阅者,由订阅者自行监听 def update(self, content): print(self.__class__.__name__ + "::update() [subject.name = " + self.subject.name + " content = " + content + "]")
# ConcreteObserver2.py 具体的观察者实现类,也可以看成订阅者,关联对应的主题类。# 不同的观察者可以对应不同的主题。from src.ObserverAPI import ObserverAPI# 具体的观察者实现类,也可以看成订阅者,关联对应的主题类。# 不同的观察者可以对应不同的主题。class ConcreteObserver2(ObserverAPI): # 这里没有在构造器就绑定某个主题,而是从客户角度去注册观察者 # 观察者发出更新通知,观察者自行监听 # def update(self, content): # print(self.__class__.__name__ + "::update() [content = " + content +"]") pass
抽象主题类# Subject.py 定义抽象主题类或者接口,供具体主题类继承class Subject: def __init__(self, name): self.name = name self.observers = [] def get_name(self): return self.name def set_name(self, name): self.name = name def register(self, observer): print(self.__class__.__name__ + "::register() [observer = " + observer.__class__.__name__ + "]") self.observers.append(observer) def remove(self, observer): self.observers.remove(observer) # 通知由具体类来实现逻辑 def notify(self, name): pass
具体主题类// ConcreteSubject.py 观察者主题类,也是发布者,重写具体的通知方法。不同主题可以关联不同的观察者。from src.Subject import Subject# 观察者主题类,也是发布者,重写具体的通知方法。不同主题可以关联不同的观察者。class ConcreteSubject(Subject): # 不同的主题类有自己的通知方法,批量通知绑定的观察者 def notify(self, content): print(self.__class__.__name__ + "::notify() [content = " + content + "]") for observer in self.observers: observer.update(content)
测试调用import sysimport osos_path = os.getcwd()sys.path.append(os_path)from src.ConcreteSubject import ConcreteSubjectfrom src.ConcreteObserver import ConcreteObserverfrom src.ConcreteObserver2 import ConcreteObserver2def test(): """ * 观察者模式应用非常广泛,主要是观察者提前绑定到发布者 * 当发布者发布消息时,批量广播通知,而无需逐一通知 * 观察者监听到消息后自己决定采取哪一种行为 """ # 定义一个主题,也就是发布者 concrete_subject = ConcreteSubject("subject1") # 再声明观察者,通过构造器注册到主题上 observer1 = ConcreteObserver(concrete_subject, "observer1") # 也可以单独给主题注册一个新的观察者 observer2 = ConcreteObserver2("observer2") concrete_subject.register(observer2) # 可以移除观察者对象 # concrete_subject.remove(observer1) # 主题开始发布新通知,各观察者自动更新 concrete_subject.notify("hello, this is broadcast.")if __name__ == "__main__": print(__file__) print("test start:") test()
更多语言版本不同语言实现设计模式:https://github.com/microwind/design-pattern
-
金都城:黄金开启三浪下跌反弹仍是高空,原油将继续走强在一系列强势经济数据支持下,9月8日,也就是本周周五ICE美元指数
-
阿根廷tini(史蒂芬说:阿根廷70万人请愿)阿根廷球迷杀人诛心了,哈哈!不甘心的法国人,20万人在网上签名请愿,
-
突发!日媒:日本外相访问乌克兰,系俄乌冲突爆发以来首次日本外相首次访乌克兰,支持其抵御俄罗斯入侵。
-
西安多区通知:9月9日10点开始预约HPV疫苗新一波的HPV疫苗预约来了!9月9日(星期六)上午10:00,雁塔区、新城区、
-
坤鹏论:读《形而上学》 学习亚里士多德的第一哲学(16)真正有本事的是疏,而非堵与禁。——坤鹏论第一卷第六章(二)原文:而
-
茶和咖啡(关于茶和咖啡简述),你们好,今天0471房产来聊聊一篇和咖啡,和咖啡简述的文章,网友们对
-
如何下载豆丁网(豆丁下载器)来为大家解答以上问题,如何下载豆丁网,豆丁下载器很多人还不知道,现
-
逾5千家上市公司披露年报,235家公司被出具非标审计意见逾5千家上市公司披露年报,235家公司被出具非标审计意见,年报,非标,证
-
“讲好山东政法故事”创意传播大赛暨“我的政法故事”征文优秀作品展示举行海报新闻记者丛萍济南报道9月8日下午,忠诚的力量——“讲好山东政法故
-
因控股股东非经营性资金占用触及违规 ST天顺及控股股东、实控人等相关责任人遭深交所通报批评深交所9月8日向ST天顺及控股股东舟山天顺股权投资有限公司,控股股东关
-
曼联女足首任主帅是曾入狱的恋童癖,但曼联仍邀他参加俱乐部活动曼联女足首任主帅是曾入狱的恋童癖,但曼联仍邀他参加俱乐部活动,英超,
-
房地产收并购市场热度回升 八月交易额明显增长房地产收并购市场8月热度回升显著,企业正在加快处置资产回笼资金。根
-
合肥一中学班主任向学生推销教辅材料 校方:行为错误,已纠正合肥一中学班主任向学生推销教辅材料 【合肥一中学班主任向学生推销40
-
五根手指各叫什么名字_五根手指分别叫什么1、拇指、食指、中指、无名指、小指。本文到此讲解完毕了,希望对大家
-
幸福蓝海9月8日快速反弹以下是幸福蓝海在北京时间9月8日13:41分盘口异动快照:  9月
-
2开双控开关接线图解(2开)1、2开纸的尺寸是:530mm×760mm不过既然是学校发的就可以就用那个啊。
-
南通向全市教育工作者发放“江海尊师卡”本报讯(记者王艳芳)为弘扬尊师重教的传统美德,充分凸显对广大教师群
-
深入分布式一致性:Raft 和 etcdRaft分布式一致性是构建可靠的分布式系统的关键要素之一。为了确保数据的一
-
北交所总经理隋强:打造资本市场改革试验田 北交所进入高质量建设2.0版本9月7日,北交所联合北京市地方金融监管局、市科委中关村管委会、市经信
-
阿维塔12重磅来袭!比极氪001更酷炫由长安汽车、华为科技以及宁德时代三家巨头共同鼎力打造的阿维塔,在市
-
厚普股份(300471)8月31日主力资金净买入1221.10万元截至2023年8月31日收盘,厚普股份(300471)报收于13 47元,上涨2 51%,
-
文昌航天发射场规划建设新一代载人登月火箭发射工位记者8月31日从文昌航天发射场获悉,目前该发射场正在规划建设新一代载
-
西安警方捣毁特大“网络水军”团伙 125人被采取刑事强制措施虚假信息、诽谤攻击、非法推广、恶评去势、操控扰乱网上舆论秩序,“网
-
广西自贸试验区加快构建面向东盟跨境产业链供应链【东盟专线】广西自贸试验区加快构建面向东盟跨境产业链供应链中新社南
-
福晟国际上半年收入1.88亿元 筹集新借贷0元观点网讯:8月31日,福晟国际控股集团有限公司发布了截至2023年6月30日
-
2023暑期档票房206.08亿2023暑期档票房206 08亿:格隆汇8月31日|据灯塔专业版,截至8月31日21
-
婚礼现场布置设计(婚礼现场布置)精选小编来为大家解答以上问题。婚礼现场布置设计,婚礼现场布置很多人
-
福州楼市限购再松绑 “本地户籍+市区”成为政策亮点为更好满足居民刚性和改善性住房需求,促进房地产市场平稳健康发展,8
-
NH4CL的电子式和结构式(nh4cl的电子式)1、nh4+中的n的其中一对孤对电子也h形成配位键,表示为n→h,其他的就
-
镇江67个乡镇(街道)全部建立应急办 将应急管理的触角延伸到基层末梢“本次培训会议,住宿3人及以上的‘三合一’场所要通知到位、派人参加