java 观察者模式示例_观察者设计模式示例

java 观察者模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。

在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 !

目录

1.观察者模式 2.什么是观察者模式 3.实施观察者模式 4. Java的内置观察者模式 5.何时使用观察者模式 6.下载源代码

1.观察者模式

体育大厅是运动爱好者的理想运动场所。 它们涵盖几乎所有类型的体育活动,并提供最新新闻,信息,比赛预定日期,有关特定球员或球队的信息。 现在,他们计划提供实时评论或比赛分数作为SMS服务,但仅针对其高级用户。 他们的目标是在短时间间隔后通过短信发送实时比分,比赛情况和重要事件。 作为用户,您需要订阅该程序包,并且在进行实时比赛时,您会收到一条有关实时评论的短信。 该站点还提供了一个随时取消订阅包的选项。

作为开发人员,运动大厅要求您为他们提供此新功能。 体育大厅的记者将坐在比赛中的评论框内,并将实时评论更新为评论对象。 作为开发人员,您的工作是通过从评论对象(如果有)中获取评论来向注册用户提供评论。 进行更新时,系统应通过向订阅的用户发送SMS来更新他们。

这种情况清楚地显示了比赛与用户之间的一对多映射,因为可能有许多用户订阅单个比赛。 观察者设计模式最适合这种情况,让我们了解一下这种模式,然后为Sport Lobby创建功能。

2.什么是观察者模式

观察者模式是一种行为模式,它与对象之间的职责分配有关。 行为模式表征了复杂的控制流,这些流在运行时很难遵循。 它们将您的注意力从控制流上移开,让您仅专注于对象的互连方式。

观察者模式定义了对象之间的一对多依赖关系,因此当一个对象改变状态时,其所有依赖关系都会得到通知并自动更新。 观察者模式描述了这些依赖关系。 此模式中的关键对象是主题和观察者。 主题可以具有任意数量的从属观察者。 只要对象的状态发生变化,就会通知所有观察者。 作为响应,每个观察者将查询主题以使其状态与主题状态同步。

了解观察者模式的另一种方法是发布者与订阅者之间的关系。 例如,假设您订阅了自己喜欢的体育或时尚杂志的杂志。 每当发行新期刊时,它就会交付给您。 如果您在不再需要该杂志时取消订阅,则该杂志将不会发送给您。 但是出版商继续像以前一样工作,因为还有其他人也订阅了该杂志。

类图1

图1

观察者模式有四个参与者:

  1. 主题,用于注册观察者。 对象使用此接口注册为观察者,也将自己从观察者中删除。
  2. 观察者,定义了一个对象的更新接口,该对象应该在主题更改时得到通知。 所有观察者都需要实现Observer接口。 该接口具有update()方法,当Subject的状态更改时会调用该方法。
  3. ConcreteSubject,将感兴趣的状态存储到ConcreteObserver对象。 状态更改时,它将向其观察者发送通知。 具体主题始终实现Subject接口。 每当状态更改时, notifyObservers()方法用于更新所有当前观察者。
  4. ConcreateObserver,维护对ConcreteSubject对象的引用,并实现Observer接口。 每个观察者都向具体主题注册以接收更新。

3.实施观察者模式

让我们看看如何在开发运动大厅功能时使用观察者模式。 有人将更新具体主题的对象,而您的工作是更新在具体主题对象中注册的对象的状态。 因此,只要具体主体对象的状态发生变化,就应该通知其所有依赖对象,然后进行更新。

类图2

图2

基于此,我们首先创建一个Subject接口。 在“主题”界面中,有三种主要方法,可以根据需要添加其他一些方法(如果需要)。

package com.javacodegeeks.patterns.observerpattern;public interface Subject {public void subscribeObserver(Observer observer);public void unSubscribeObserver(Observer observer);public void notifyObservers();public String subjectDetails();
}

Subject界面中的三个关键方法是:

  1. subscribeObserver ,用于订阅观察者,或者我们可以说注册观察者,以便如果主题的状态发生变化,则应通知所有这些观察者。
  2. unSubscribeObserver ,用于取消订阅观察者,因此,如果主题的状态发生变化,则不应通知该未订阅的观察者。
  3. notifyObservers ,当主题状态发生变化时,此方法通知注册的观察者。

并且可选地,还有一个方法subjectDetails() ,这是一个简单的方法,并且根据您的需要。 在这里,其工作是返回主题的详细信息。

现在,让我们看看Observer界面。

package com.javacodegeeks.patterns.observerpattern;public interface Observer {public void update(String desc);public void subscribe();public void unSubscribe();
}
  1. 当主题状态发生变化时,主题会在观察者上调用update(String desc)方法,以通知该方法。
  2. subscribe() ,方法用于向主题订阅自身。
  3. unsubscribe() ,方法用于取消订阅主题。
package com.javacodegeeks.patterns.observerpattern;public interface Commentary {public void setDesc(String desc);
}

报告者使用以上接口来更新评论对象的实时评论。 这是一个可选接口,仅用于遵循代码与接口的原则 ,与Observer模式无关。 您应该在适用的情况下应用oops原则以及设计模式。 该界面仅包含一种用于更改具体主题对象状态的方法。

package com.javacodegeeks.patterns.observerpattern;import java.util.List;public class CommentaryObject implements Subject,Commentary{private final List<Observer>observers;private String desc;private final String subjectDetails;public CommentaryObject(List<Observer>observers,String subjectDetails){this.observers = observers;this.subjectDetails = subjectDetails;}@Overridepublic void subscribeObserver(Observer observer) {observers.add(observer);}@Overridepublic void unSubscribeObserver(Observer observer) {int index = observers.indexOf(observer);observers.remove(index);}@Overridepublic void notifyObservers() {System.out.println();for(Observer observer : observers){observer.update(desc);}}@Overridepublic void setDesc(String desc) {this.desc = desc;notifyObservers();}@Overridepublic String subjectDetails() {return subjectDetails;}}

上面的类用作实现Subject接口并提供其实现的具体主题。 它还将引用存储到已注册的观察者。

package com.javacodegeeks.patterns.observerpattern;public class SMSUsers implements Observer{private final Subject subject;private String desc;private String userInfo;public SMSUsers(Subject subject,String userInfo){if(subject==null){throw new IllegalArgumentException("No Publisher found.");}this.subject = subject;this.userInfo = userInfo;}@Overridepublic void update(String desc) {this.desc = desc;display();}private void display(){System.out.println("["+userInfo+"]: "+desc);}@Overridepublic void subscribe() {System.out.println("Subscribing "+userInfo+" to "+subject.subjectDetails()+" ...");this.subject.subscribeObserver(this);System.out.println("Subscribed successfully.");}@Overridepublic void unSubscribe() {System.out.println("Unsubscribing "+userInfo+" to "+subject.subjectDetails()+" ...");this.subject.unSubscribeObserver(this);System.out.println("Unsubscribed successfully.");}}

上面的类是实现Observer接口的具体观察者类。 它还存储对它订阅的主题的引用,以及可选的用于显示用户信息的userInfo变量。

现在,让我们测试示例。

package com.javacodegeeks.patterns.observerpattern;import java.util.ArrayList;public class TestObserver {public static void main(String[] args) {Subject subject = new CommentaryObject(new ArrayList<Observer>(), "Soccer Match [2014AUG24]");Observer observer = new SMSUsers(subject, "Adam Warner [New York]");observer.subscribe();System.out.println();Observer observer2 = new SMSUsers(subject, "Tim Ronney [London]");observer2.subscribe();Commentary cObject = ((Commentary)subject);cObject.setDesc("Welcome to live Soccer match");cObject.setDesc("Current score 0-0");System.out.println();observer2.unSubscribe();System.out.println();cObject.setDesc("It's a goal!!");cObject.setDesc("Current score 1-0");System.out.println();Observer observer3 = new SMSUsers(subject, "Marrie [Paris]");observer3.subscribe();System.out.println();cObject.setDesc("It's another goal!!");cObject.setDesc("Half-time score 2-0");}}

上面的示例将产生以下输出:

Subscribing Adam Warner [New York] to Soccer Match [2014AUG24] ...
Subscribed successfully.Subscribing Tim Ronney [London] to Soccer Match [2014AUG24] ...
Subscribed successfully.[Adam Warner [New York]]: Welcome to live Soccer match
[Tim Ronney [London]]: Welcome to live Soccer match[Adam Warner [New York]]: Current score 0-0
[Tim Ronney [London]]: Current score 0-0Unsubscribing Tim Ronney [London] to Soccer Match [2014AUG24] ...
Unsubscribed successfully.[Adam Warner [New York]]: It's a goal!![Adam Warner [New York]]: Current score 1-0Subscribing Marrie [Paris] to Soccer Match [2014AUG24] ...
Subscribed successfully.[Adam Warner [New York]]: It's another goal!!
[Marrie [Paris]]: It's another goal!![Adam Warner [New York]]: Half-time score 2-0
[Marrie [Paris]]: Half-time score 2-0

如您所见,起初有两个用户订阅了足球比赛并开始接收评论。 但是后来有一个用户取消了订阅,因此该用户没有再收到评论。 然后,另一个用户订阅并开始获取评论。

所有这一切都是动态发生的,无需更改现有代码,不仅如此,假设该公司是否要在电子邮件上广播评论,或者任何其他公司希望与该公司进行合作以广播评论。 您需要做的就是创建两个新类,例如UserEmailColCompany并通过实现Observer接口使它们成为主题的Observer 。 据Subject知道它是观察者,它将提供更新。

4. Java的内置观察者模式

Java内置了对Observer模式的支持。 最通用的是java.util包中的Observer接口和Observable类。 这些与我们的“主题和观察者”界面非常相似,但是为您提供了许多现成的功能。

让我们尝试使用Java的内置Observer模式实现上述示例。

package com.javacodegeeks.patterns.observerpattern;import java.util.Observable;public class CommentaryObjectObservable extends Observable implements Commentary {private String desc;private final String subjectDetails;public CommentaryObjectObservable(String subjectDetails){this.subjectDetails = subjectDetails;}@Overridepublic void setDesc(String desc) {this.desc = desc;setChanged();notifyObservers(desc);}public String subjectDetails() {return subjectDetails;}
}

这次我们扩展了Observable类,使我们的类成为一个主体,请注意,上述类没有任何对观察者的引用,它是由父类处理的,即Observable类。 但是,我们声明了setDesc方法来更改对象的状态,如上例所示。 setChanged方法是上层类的方法,用于将更改的标志设置为true。 notifyObservers方法通知其所有观察者,然后调用clearChanged方法以指示此对象不再更改。 每个观察者都有使用两个参数调用的update方法:一个observable对象和arg参数。

package com.javacodegeeks.patterns.observerpattern;import java.util.Observable;public class SMSUsersObserver implements java.util.Observer{private String desc;private final String userInfo;private final Observable observable;public SMSUsersObserver(Observable observable,String userInfo){this.observable = observable;this.userInfo = userInfo;}public void subscribe() {System.out.println("Subscribing "+userInfo+" to "+((CommentaryObjectObservable)(observable)).subjectDetails()+" ...");this.observable.addObserver(this);System.out.println("Subscribed successfully.");}public void unSubscribe() {System.out.println("Unsubscribing "+userInfo+" to "+((CommentaryObjectObservable)(observable)).subjectDetails()+" ...");this.observable.deleteObserver(this);System.out.println("Unsubscribed successfully.");}@Overridepublic void update(Observable o, Object arg) {desc = (String)arg;display();}private void display(){System.out.println("["+userInfo+"]: "+desc);}}

让我们讨论一些关键方法。

上面的类实现了Observer接口,该接口具有一个关键方法update ,当主题调用notifyObservers方法时会调用该方法。 update方法采用一个Observable对象和一个arg作为参数。

addObserver方法用于将观察者注册到主题,而deleteObserver方法用于将观察者从主题列表中删除。

让我们测试这个例子。

package com.javacodegeeks.patterns.observerpattern;public class Test {public static void main(String[] args) {CommentaryObjectObservable obj = new CommentaryObjectObservable("Soccer Match [2014AUG24]");SMSUsersObserver observer = new SMSUsersObserver(obj, "Adam Warner [New York]");SMSUsersObserver observer2 = new SMSUsersObserver(obj,"Tim Ronney [London]");observer.subscribe();observer2.subscribe();System.out.println("------------------------------------------------------");obj.setDesc("Welcome to live Soccer match");obj.setDesc("Current score 0-0");observer.unSubscribe();obj.setDesc("It's a goal!!");obj.setDesc("Current score 1-0");}
}

上面的示例将产生以下输出:

Subscribing Adam Warner [New York] to Soccer Match [2014AUG24] ...
Subscribed successfully.
Subscribing Tim Ronney [London] to Soccer Match [2014AUG24] ...
Subscribed successfully.
------------------------------------------------------
[Tim Ronney [London]]: Welcome to live Soccer match
[Adam Warner [New York]]: Welcome to live Soccer match
[Tim Ronney [London]]: Current score 0-0
[Adam Warner [New York]]: Current score 0-0
Unsubscribing Adam Warner [New York] to Soccer Match [2014AUG24] ...
Unsubscribed successfully.
[Tim Ronney [London]]: It's a goal!!
[Tim Ronney [London]]: Current score 1-0

上面的类创建一个主题和两个观察者。 observersubscribe方法将其自身添加到主题观察者列表中。 然后setDesc更改主题的状态,该主题调用setChanged方法将更改标志设置为true,并通知观察者。 结果,调用了观察者的update方法,该方法在内部对display方法进行分类以显示结果。 后来,一位观察者unsubscribe d,即从观察者列表中将其删除。 由于此原因,以后的评论未更新。

Java为观察者模式提供了内置功能,但是它也有其自身的缺点。 Observable是一个类,您必须对其进行子类化。 这意味着您不能将Observable行为添加到已经扩展了另一个超类的现有类上。 这限制了重用潜力。 您甚至无法创建自己的实现,以与Java的内置Observer API配合使用。 Observable API中的某些方法受到保护。 这意味着除非已将Observable子类setChange否则无法调用setChange类的方法。 而且,您甚至无法创建Observable类的实例并将其与自己的对象组合在一起,因此必须子类化。 此设计违反了“优先继承而不是继承”的设计原则。

5.何时使用观察者模式

在以下任何一种情况下,请使用Observer模式:

  1. 当抽象具有两个方面时,一个方面依赖于另一个方面。 将这些方面封装在单独的对象中,使您可以分别更改和重用它们。
  2. 当更改一个对象需要更改其他对象时,您不知道需要更改多少个对象。
  3. 一个对象何时应该能够通知其他对象而无需假设这些对象是谁。 换句话说,您不希望这些对象紧密耦合。

6.下载源代码

这是“观察者模式”的一课。 您可以在此处下载源代码: ObserverPattern –第7课

翻译自: https://www.javacodegeeks.com/2015/09/observer-design-pattern.html

java 观察者模式示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336960.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

int类型存小数 mysql_MySQL基本数据类型

1&#xff09;整形1.介绍分类&#xff1a;tinyint , smallint , mediumint , int , bigint 应用场景&#xff1a;存储年龄&#xff0c;等级&#xff0c;id&#xff0c;各种号码等典型存储范围介绍:https://images2017.cnblogs.com/blog/1036857/201708/1036857-201708011814337…

枚举重名_举重设计模式示例

枚举重名本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01…

装饰着模式示例_装饰器设计模式示例

装饰着模式示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &…

强烈推荐!10个超赞的C语言开源项目

关注星标&#xff0c;每天学习C语言新技能因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源&#xff1a;网络今天给大家分享10个超赞的C语言开源项目&#xff0c;希望这些内容能对大家有所帮助&#xff01;01WebbenchWebbench是一个在 L…

以外的文件 删除_原来C盘还可以删除这五个文件,难怪电脑越来越卡!

马上就要年底了&#xff0c;大家肯定都是欢欢喜喜准备过年&#xff0c;将家里变得焕然一新。韩博士也捯饬好大包小包打算风风火火赶回家&#xff0c;结果刚打开电脑&#xff0c;哦豁&#xff0c;立马卡到爆炸。想着都年底了&#xff0c;这电脑还打算给我搞出什么幺蛾子&#xf…

设计模式示例_复合设计模式示例

设计模式示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#x…

给大家收集了一些C语言代码优化的方法!

关注星标&#xff0c;每天学习C语言新技能因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源&#xff1a;网络在本篇文章中&#xff0c;我收集了很多经验和方法。应用这些经验和方法&#xff0c;可以帮助我们从执行速度和内存使用等方面来…

设计模式示例_介体设计模式示例

设计模式示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#x…

清空list_还在为邮箱爆掉而烦恼吗?学会清空你的收件箱

less is more | 越不繁&#xff0c;越不凡还在为邮箱爆掉而烦恼吗&#xff1f;学会清空你的收件箱我一般只用Gmail收发邮件&#xff0c;而且处理邮件已经成为日常工作的核心之一。我每个小时能收到大量邮件&#xff0c;并且快速回复。但是&#xff0c;有一件事要特别提一下&…

这才是B站的正确打开方式!

关注星标&#xff0c;每天学习C语言新技能因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源&#xff1a;网络每天都在用B站刷杂七杂八的视频&#xff0c;有没有考虑过挖掘一些优质UP主&#xff1f;想要发掘优质UP主&#xff0c;靠B站官方…

pcl_openmap_OpenMap教程–第1部分

pcl_openmap介绍 本系列教程将向您展示如何使用OpenMap GIS Java Swing库构建Java应用程序。 OpenMap的开发人员指南是非常有用的文档&#xff0c;描述了OpenMap的体系结构&#xff0c;但没有说明如何逐步启动和构建应用程序。 源代码附带的示例很有用&#xff0c;但还不够。 …

网页编程从入门到精通 杨凡_干货 | web前端入门基础知识

一名合格的web前端工程师必须得掌握HTML、CSS和JavaScript。只懂其中一个或两个还不行&#xff0c;你必须对这三门语言都很熟悉。也不是说必须对这三门语言都非常精通&#xff0c;但你至少要能够运用它们完成大多数任务&#xff0c;而无需地频繁地寻求别人的帮助。今天给大家分…

100 个网络基础知识

关注星标&#xff0c;每天学习C语言新技能因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源&#xff1a;网络1)什么是链接?链接是指两个设备之间的连接。它包括用于一个设备能够与另一个设备通信的电缆类型和协议。2)OSI 参考模型的层次…

策略模式示例代码_策略设计模式示例

策略模式示例代码本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &am…

加白名单_Android保活从入门到放弃:乖乖引导用户加白名单吧

1、引言IM在Android上的保活问题经常在即时通讯网的论坛和技术群里被讨论&#xff0c;自从Android 8.0后系统大大降低了后台运行应用的保活容忍度(详见《Android P正式版即将到来&#xff1a;后台应用保活、消息推送的真正噩梦》)&#xff0c;保活从黑科技横行的时代进入了技术…

子模板继承父模板示例_模板设计模式示例

子模板继承父模板示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看…

10个超赞的C语言开源项目!

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删今天分享10个超赞的C语言开源项目&#xff0c;希望这些内容能对大家有所帮助&#xff01;目录&#xff1a;1. Webbench2. Tinyhttpd3. cJSON4. C…

jboss eap 7_使用JBoss EAP 7的HTTP / 2

jboss eap 7就在几天前&#xff0c;新的JBoss EAP 7 ALPHA版本已经发布。 而且我已经写过博客&#xff0c;介绍如何开始使用它 。 一个非常有趣的部分是HTTP / 2支持&#xff0c;它已作为技术预览添加。 它由新的Web服务器Untertow提供。 HTTP / 2通过压缩头并在同一TCP连接上多…

Modern C++ 最核心的变化是什么?

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删个人觉得最核心的变化是右值引用的引入&#xff0c;右值引用是 C 走向现代化的最重要一步。建议每一位 C 开发者都应该深入去了解并充分使用它。…

设计模式示例_命令设计模式示例

设计模式示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#x…