前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Head First 设计模式之观察者模式,你我都是发布者和订阅者

Head First 设计模式之观察者模式,你我都是发布者和订阅者

作者头像
用户4361942
发布2019-05-24 17:02:11
7550
发布2019-05-24 17:02:11
举报
文章被收录于专栏:java程序员思维java程序员思维

观察者模式

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

观察者模式四大角色

Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供新增、删除、通知观察者的方法。

ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。

Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。

ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新

使用场景

商品变更的时候,需要更新商品缓存、发布商品详情页、更新搜索索引,传统做法,在商品update方法处,分别调用更新商品缓存接口、发布商品接口、更新搜索索引接口。代码耦合度很高,如果增加一个新的逻辑,需要修改update方法,如果商品修改不需要更新缓存了,同样需要修改update方法。通过引入观察者模式,通过消息中间件的方式可以进行解耦,当商品发生修改的时候,发送一个消息,商品缓存应用可以订阅此消息,进行缓存的更新。商品发布系统,订阅此消息,重新发布商品。搜索应用,订阅此消息,增量更新索引。

如果商品更改有其他的业务逻辑,可以通过消息订阅和消费,增加相应的逻辑。如果要去掉某个逻辑,只要取消消息订阅,不再消费此消息即可。观察者模式通过发布和订阅的方式,实现业务的解耦。

代码实现

代码语言:javascript
复制
public interface Subject {
 //添加观察者
 void addObserver(Observer obj);
 //移除观察者
 void deleteObserver(Observer obj);
 //当主题方法改变时,这个方法被调用,通知所有的观察者
 void notifyObserver();
}
代码语言:javascript
复制
public class StudentObserver implements Observer{
 //保存一个Subject的引用,以后如果可以想取消订阅,有了这个引用会比较方便
 private Subject subject;
 //学生的姓名,用来标识不同的学生对象
 private String name;
 //构造器用来注册观察者
 public StudentObserver(String name,TeacherSubject teacherSubject) {
 this.name=name;
 this.subject = teacherSubject;
 //每新建一个学生对象,默认添加到观察者的行列
 teacherSubject.addObserver(this);
 }
 public void update(String info) {
 System.out.println(name+"得到作业:"+info);
 }
}
代码语言:javascript
复制
public interface Subject {
 //添加观察者
 void addObserver(Observer obj);
 //移除观察者
 void removeObserver(Observer obj);
 //当主题方法改变时,这个方法被调用,通知所有的观察者
 void notifyObserver();
}
代码语言:javascript
复制
public class StudentObserver implements Observer{
 //保存一个Subject的引用,以后如果可以想取消订阅,有了这个引用会比较方便
 private Subject subject;
 //学生的姓名,用来标识不同的学生对象
 private String name;
 //构造器用来注册观察者
 public StudentObserver(String name,TeacherSubject teacherSubject) {
 this.name=name;
 this.subject = teacherSubject;
 //每新建一个学生对象,默认添加到观察者的行列
 teacherSubject.addObserver(this);
 }
 public void update(String info) {
 System.out.println(name+"得到作业:"+info);
 }
}
代码语言:javascript
复制
public class TestObserver {
 public static void main(String[] args) {
 TeacherSubject teacher = new TeacherSubject();
 StudentObserver zhangSan = new StudentObserver("张三", teacher);
 StudentObserver LiSi = new StudentObserver("李四", teacher);
 StudentObserver WangWu = new StudentObserver("王五", teacher);
 teacher.setHomework("第二页第六题");
 System.out.println("----------------");
 teacher.setHomework("第三页第七题");
 System.out.println("----------------");
 teacher.setHomework("第五页第八题");
 }
}

运行结果:

代码不是特别的严谨,没有考虑多线程问题,不是线程安全的,用于生产环境,需要做同步或者增加锁控制。java中jdk提供了相关的工具类,java.uitl包下的Observer和Observable,这个是同步的,支持多线程。java自带jdk实现方法如下:

代码语言:javascript
复制
public class Message {
 private String title;
 private String content;
 public String getTitle() {
 return title;
 }
 public void setTitle(String title) {
 this.title = title;
 }
 public String getContent() {
 return content;
 }
 public void setContent(String content) {
 this.content = content;
 }
 public Message(String title, String content) {
 this.title = title;
 this.content = content;
 }
 @Override
 public String toString() {
 return "Message{" +
 "title='" + title + '\'' +
 ", content='" + content + '\'' +
 '}';
 }
}
代码语言:javascript
复制
//订阅者
public class MessageObserver implements Observer {
 private String title;
 public String getTitle() {
 return title;
 }
 public void setTitle(String title) {
 this.title = title;
 }
 public MessageObserver(String title) {
 this.title = title;
 }
 public void update(Observable o, Object arg) {
 System.out.println("observer :" + title + ",receive a message" + arg.toString());
 }
}
代码语言:javascript
复制
//发布者
public class MessagePublishObservable extends Observable {
 private Message message;
 public MessagePublishObservable(Message message) {
 this.message = message;
 }
 public void pushMessage(){
 setChanged();
 notifyObservers(message);
 }
 public Message getMessage() {
 return message;
 }
 public void setMessage(Message message) {
 this.message = message;
 }
 @Override
 public synchronized void addObserver(Observer o) {
 super.addObserver(o);
 }
 @Override
 public synchronized void deleteObserver(Observer o) {
 super.deleteObserver(o);
 }
 @Override
 public void notifyObservers() {
 super.notifyObservers();
 }
 @Override
 public void notifyObservers(Object arg) {
 super.notifyObservers(arg);
 }
 @Override
 protected synchronized void setChanged() {
 super.setChanged();
 }
}
代码语言:javascript
复制
public class Test {
 public static void main(String[] args) {
 MessageObserver messageObserverTopicA = new MessageObserver("A");
 MessageObserver messageObserverTopicB = new MessageObserver("B");
 MessageObserver messageObserverTopicC = new MessageObserver("C");
 MessagePublishObservable messagePublishObservable = new MessagePublishObservable(new Message("关注","欢迎关注享知行"));
 //a关注了享知行
 messagePublishObservable.addObserver(messageObserverTopicA);
 //b关注了享知行
 messagePublishObservable.addObserver(messageObserverTopicB);
 //c关注了享知行
 messagePublishObservable.addObserver(messageObserverTopicC);
 messagePublishObservable.pushMessage();
 messagePublishObservable.setMessage(new Message("文章更新","公众号享知行更新啦"));
 messagePublishObservable.pushMessage();
 }
}

运行结果:

优缺点

优点:发布者和订阅者是松耦合的,发布者和订阅者之间互不影响,满足开闭原则,当有变化的时候,实时,高效的通知订阅者。

缺点:如果一个发布者对象有很多直接和间接的订阅者的话,将所有的订阅者都通知到会花费很多时间。如果在发布者之间有循环依赖的话,发布者会触发它们之间进行循环调用,导致系统崩溃。

生活中的观察者模式

老师布置作业,采用的就是观察者模式,老师是信息的发布者,学生是订阅者,老师布置作业只需要布置一遍即可,所有的学生,都能收到这个任务。

邮件组也是观察者模式,可以动态的增加和删除组成员,技术部的所有成员创建一个邮件组,如果需要发送邮件通知所有技术部的人,只要发送一封邮件给技术部邮件组即可,既方便又不会遗漏。如果有员工入职加入邮件组,有员工离职则从邮件组删除。

群社区也是观察者模式的一种形式,有相同爱好兴趣的人加入到同一个群,每一个人既是消息的发布者,也是订阅者,让大家的沟通更实时高效。

专栏的订阅,公众号的关注也是属于观察者模式,内容生产者,有新的内容更新,会通知所有的订阅者,你如果喜欢“享知行”,并关注了公众号“享知行”,只要享知行有内容更新,会通知所有的粉丝。

直播和视频,同样也是观察者模式,内容生产者,直播或者把录好的视频上传,如果你感兴趣,点开观看,所有人看到的都是同样的内容。

app消息订阅、报纸订阅、新闻订阅等等都是观察者模式,观察者模式无处不在,我们既是内容生产者也是内容的消费者。

我的启发

我们既是内容的生产者,不断的创造内容。作为内容的生产者,请保持内容的质量。我们也是内容的消费者,不断的消费内容,作为内容的消费者,请保持批判的精神。

上一篇:Head first 设计模式之策略模式,来源于生活,用之于生活

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java程序员思维 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云直播
云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档