文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

一文带你彻底搞懂发布与订阅设计

2024-12-02 23:58

关注

一、介绍

我们常说的发布订阅设计模式,也叫观察者模式,也就是事件监听机制,观察者模式订阅了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当这个主题对象发生改变时,会通知所有的观察者对象,使他们能够自动的更新自己!

一个软件系统要求某个对象在发生变化时,某些其他的对象作出相应的改变,能做到这点的设计方案有很多,但观察者模式是满足这一要求的各种设计方案中最重要的一种。

从整体来看,观察者模式所涉及的角色有:

废话也不多说了,下面我们直接讲案例!

二、示例

抽象主题角色,有增加观察者、删除观察者、通知观察者的功能,内容如下:

  1. public abstract class AbstractSubject { 
  2.  
  3.      
  4.     private List list = new ArrayList(); 
  5.  
  6.      
  7.     public void add(Observer observer){ 
  8.         list.add(observer); 
  9.         System.out.println("add an observer"); 
  10.     } 
  11.  
  12.      
  13.     public void remove(Observer observer){ 
  14.         list.remove(observer); 
  15.         System.out.println("delete an observer"); 
  16.     } 
  17.  
  18.      
  19.     public void notifyObservers(String state){ 
  20.         for (int i = 0; i < list.size(); i++) { 
  21.             list.get(i).update(state); 
  22.         } 
  23.     } 

具体主题角色,这个change方法放在子类中是因为可能不同的主题在改变观察者状态的时候会做一些不同的操作,因此就不统一放在父类Subject里面了,内容如下:

  1. public class ConcreteSubject extends AbstractSubject{ 
  2.  
  3.     private String state; 
  4.  
  5.     public void change(String newState){ 
  6.         state = newState; 
  7.         System.out.println("主题状态:" + state); 
  8.  
  9.         //状态发生改变,通知所有的观察者 
  10.         super.notifyObservers(state); 
  11.     } 

观察者接口,内容如下:

  1. public interface Observer { 
  2.  
  3.      
  4.     void update(String state); 

具体观察者实现了观察者接口,内容如下:

  1. public class ConcreteObserver implements Observer{ 
  2.  
  3.     @Override 
  4.     public void update(String state) { 
  5.         System.out.println("观察者,收到状态:" + state); 
  6.     } 

客户端调用代码,一旦主题调用了change方法改变观察者的状态,那么观察者Observer里面的observerState全都改变了,内容如下:

  1. public class ObserverClient { 
  2.  
  3.     public static void main(String[] args) { 
  4.         //创建一个主题角色 
  5.         ConcreteSubject subject = new ConcreteSubject(); 
  6.  
  7.         //创建观察者对象 
  8.         ConcreteObserver observer = new ConcreteObserver(); 
  9.  
  10.         //将观察者加入主题对象上 
  11.         subject.add(observer); 
  12.  
  13.         //改变主题状态 
  14.         subject.change("hello world"); 
  15.     } 

运行结果如下:

  1. add an observer 
  2. 主题状态:hello world 
  3. 观察者,收到状态:hello world 

这里只添加了一个观察者,有兴趣的可以试试看多添加几个观察者,效果都是一样的,主题角色改变状态,观察者状态全变。

三、应用

观察者模式的两种模型

两种模型的比较

JDK是有直接支持观察者模式的,就是java.util.Observer这个接口,内容如下:

  1. public interface Observer { 
  2.      
  3.     void update(Observable o, Object arg); 

这就是观察者的接口,定义的观察者只需要实现这个接口就可以了。update()方法,被观察者对象的状态发生变化时,被观察者的notifyObservers()方法就会调用这个方法,内容如下:

  1. public class Observable { 
  2.     private boolean changed = false
  3.     private Vector obs; 
  4.     
  5.      
  6.  
  7.     public Observable() { 
  8.     obs = new Vector(); 
  9.     } 
  10.  
  11.      
  12.     public synchronized void addObserver(Observer o) { 
  13.         if (o == null
  14.             throw new NullPointerException(); 
  15.     if (!obs.contains(o)) { 
  16.         obs.addElement(o); 
  17.     } 
  18.     } 
  19.     ... 

这是被观察者的父类,也就是主题对象。这是一个线程安全的类,是基于Vector实现的。

创建一个观察者,内容如下:

  1. import java.util.Observable; 
  2. import java.util.Observer; 
  3.  
  4. public class Watched implements Observer { 
  5.  
  6.     @Override 
  7.     public void update(Observable o, Object arg) { 
  8.         System.out.println("观察者,收到状态:" + arg); 
  9.     } 

创建一个主题,内容如下:

  1. import java.util.Observable; 
  2.  
  3. public class Subject extends Observable { 
  4.  
  5.     private String data; 
  6.  
  7.     public void setData(String newData){ 
  8.         System.out.println("主题状态:" + newData); 
  9.         data = newData; 
  10.         setChanged(); 
  11.         notifyObservers(data); 
  12.     } 

写一个main函数调用,内容如下:

  1. public class WatchedClient { 
  2.  
  3.     public static void main(String[] args) { 
  4.         //创建观察者对象 
  5.         Watched watched = new Watched(); 
  6.  
  7.         //创建主题 
  8.         Subject subject = new Subject(); 
  9.  
  10.         //将观察者对象加入主题 
  11.         subject.addObserver(watched); 
  12.  
  13.         //修改主题状态 
  14.         subject.setData("hello world"); 
  15.  
  16.     } 

运行结果,内容如下:

  1. 主题状态:hello world 
  2. 观察者,收到状态:hello world 

看到主题对象改变的时候,观察者对象的状态也随之改变。

四、总结

引入设计模式最主要的作用我认为就是两点:

使用观察者模式可以很好地做到这两点。增加观察者,直接new出观察者并注册到主题对象之后就完事了,删除观察者,主题对象调用方法删除一下就好了,其余都不用管。主题对象状态改变,内部会自动帮我们通知每一个观察者,是不是很方便呢?

观察者模式主要应用场景有:

 

 

来源: Java极客技术内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯