java观察者模式

 像activeMQ等消息队列中,我们经常会使用发布订阅模式,但是你有没有想过,客户端时如何及时得到订阅的主题的信息?其实就里就用到了观察者模式。在软件系统中,当一个对象的行为依赖于另一个对象的状态时,观察者模式就相当有用。如果不使用观察者模式提供的通用结构,而需要我们实现类似的功能,想想我们该如何实现,我们只能在另外一个线程不断监听对象所依赖的状态。当然下面的例子都是基于一个进程内观察者模式的举例,你可能会和我当初一样不解,消息队列中的消费者是通过socket进行通信得到订阅的主题的信息。其实还是一回事的,被观察者(主题)里面会维护一个与它有订阅的所有消费者的连接,当被观察者(主题)里面添加一个消息时,就会调用自身的方法,把该消息通过维持的socket发送给所有订阅的消费者。

  下次再跳槽,我就不是仅仅调侃我掌握kafka等消息队列的特性了,我又可以结合设计模式来侃我对消息队列的理解,这个逼吹的响亮吧。

    观察者模式可以用于事件监听,通知发布等场合。可以确保观察者在不使用轮询监控的情况下,及时收到相关的消息和事件。

原文和作者一起讨论:http://www.cnblogs.com/intsmaze/p/6017508.html

新浪微博:intsmaze刘洋洋哥

模式动机

建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。

模式定义

观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式。观察者模式是一种对象行为型模式。

模式分析

观察者模式描述了如何建立对象与对象之间的依赖关系,如何构造满足这种需求的系统。这一模式中的关键对象是观察目标和观察者,一个目标可以有任意数目的与之相依赖的观察者,一旦目标的状态发生改变,所有的观察者都将得到通知。作为对这个通知的响应,每个观察者都将即时更新自己的状态,以与目标状态同步,这种交互也称为发布-订阅(publish-subscribe)。目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅它并接收通知。

观察者模式顺序图如下所示:

模式应用

(1) JDK1.1版本及以后的各个版本中,事件处理模型采用基于观察者模式的委派事件模型(Delegation Event Model, DEM)。

在DEM中,事件的发布者称为事件源(Event Source),而订阅者叫做事件监听器(Event Listener),在这个过程中还可以通过事件对象(Event Object)来传递与事件相关的信息,可以在事件监听者的实现类中实现事件处理,因此事件监听对象又可以称为事件处理对象。

事件源对象、事件监听对象(事件处理对象)和事件对象构成了Java事件处理模型的三要素。

(2) 除了AWT中的事件处理之外,Java语言解析XML的技术SAX2以及Servlet技术的事件处理机制都基于DEM,它们都是观察者模式的应用。

(3) 观察者模式在软件开发中应用非常广泛,如某电子商务网站可以在执行发送操作后给用户多个发送商品打折信息,某团队战斗游戏中某队友牺牲将给所有成员提示等等,凡是涉及到一对一或者一对多的对象交互场景都可以使用观察者模式。 

Java语言提供的对观察者模式的支持

在java.util.Observable类中,已经实现了主要的功能,如增加观察者,删除观察者和通知观察者,我们可以直接通过继承Observable使用这些功能。

java.util.Observer接口是观察者接口,它的update方法会在java.util.Observable中的notifyObservers方法中被回调,以获得最新的状态变化。通常在观察者模式中,Observer接口就是我们程序的核型扩展对象,具体业务逻辑会被封装在update方法中。

public class Observable {      
    private boolean changed = false;      
    private Vector obs;      
         
    //创建被观察者时就创建一个它持有的观察者列表,注意,这个列表是需要同步的。      
    public Observable() {      
        obs = new Vector();      
    }      
     
    /**    
     * 添加观察者到观察者列表中去    
     */     
    public synchronized void addObserver(Observer o) {      
        if (o == null)      
            throw new NullPointerException();      
    if (!obs.contains(o)) {      
        obs.addElement(o);      
    }      
    }      
     
    /**    
     * 删除一个观察者    
     */     
    public synchronized void deleteObserver(Observer o) {      
        obs.removeElement(o);      
    }           
     
    /**    
     * 这个方法接受一个参数,这个参数一直传到观察者里,以供观察者使用    
     */     
    public void notifyObservers(Object arg) {                
       Object[] arrLocal;           
       synchronized (this) {      
        if (!changed)      
                return;      
            arrLocal = obs.toArray();      
            clearChanged();      
        }      
        for (int i = arrLocal.length-1; i>=0; i--)      
            ((Observer)arrLocal[i]).update(this, arg);      
    }      
}     

public interface Observer {      
    void update(Observable o, Object arg);       
}    
     
public class JMSObserver implements Observer{          
    public void update(Observable o, Object arg) {      
        System.out.println("发送消息给jms服务器的观察者已经被执行");      
    }      
}     
public class Subject extends Observable{      
          
    /**    
     * 业务方法,一旦执行某个操作,则通知观察者,在队列模式中,其实就是当消息被添加到队列的时候,添加进队方法里面调用了通知方法。    
     */     
    public void doBusiness(){      
        if (true) {      
            super.setChanged();      
        }      
        notifyObservers("现在还没有的参数");      
    }      
     
          
    public static void main(String [] args) {      
        //创建一个被观察者      
        Subject subject = new Subject();      
              
        //创建观察者      
        Observer jmsObserver = new JMSObserver();      
              
        //把两个观察者加到被观察者列表中        
        subject.addObserver(jmsObserver);      
              
        //执行业务操作      
        subject.doBusiness();      
    }      
}    

MVC模式(有空,研究代码好好理解,有时加分调侃项目)

MVC模式是一种架构模式,它包含三个角色:模型(Model),视图(View)和控制器(Controller)。观察者模式可以用来实现MVC模式,观察者模式中的观察目标就是MVC模式中的模型(Model),而观察者就是MVC中的视图(View),控制器(Controller)充当两者之间的中介者(Mediator)。当模型层的数据发生改变时,视图层将自动改变其显示内容。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java 源码分析

Netty 入门

1. 粘包问题 一 .长连接与短连接: 1.长连接:Client方与Server方先建立通讯连接,连接建立后不断开, 然后再进行报文发送和接收。长连接在 net...

3857
来自专栏Clive的技术分享

实现PHP内部的通知机制,如当一个类的属性发生变化时,另外一个类就可以收到通知设计模式:观察者模式使用场景参考链接

设计模式:观察者模式 当一个对象的状态发生改变时,依赖他的对象会全部收到通知,并自动更新。 使用场景 一个事件发生后,要执行一连串更新操作。传统的编程方式,就是...

9147
来自专栏程序员的SOD蜜

单数据库,多数据库,单实例,多实例不同情况下的数据访问效率测试

最近公司的项目准备优化一下系统的性能,希望在数据库方面看有没有提升的空间,目前压力测试发现数据库服务器压力还不够大,Web服务器压力也不是很大的情况下,前台页面...

24710
来自专栏更流畅、简洁的软件开发方式

基于jQuery的ajax对WebApi和OData的封装我们还是先来看看要求在看看目标:思路封装方式

基于jQuery的ajax对WebApi和OData的封装   WebApi 的使用带来了一个显著的特点,对type有一定的要求。一般ajax的type无非就是...

26610
来自专栏小樱的经验随笔

CTF---Web入门第五题 貌似有点难

貌似有点难分值:20 来源: 西普学院 难度:难 参与人数:7249人 Get Flag:2519人 答题人数:2690人 解题通过率:94% 不多说,去看题目...

3136
来自专栏比原链

剥开比原看代码17:比原是如何显示交易的详细信息的?

Gitee地址:https://gitee.com/BytomBlockchain/bytom

821
来自专栏IT派

数据工程师推荐你用的几个工具

作为数据工程师或者数据分析师,经常会跟各种数据打交道,其中,获取数据这一关是无法避免的,下面,我就将自己时常工作中用到的数据连接配置模型分享出来,供大家交流。

1184
来自专栏码神联盟

碎片化 | 第四阶段-40-Struts组件分类讲解-视频

如清晰度低,可转PC网页观看高清版本: http://v.qq.com/x/page/o0567s4azx0.html ---- ---- 版权声明:本视频...

3419
来自专栏Coding01

简述 Laravel Model Events 的使用

最近一直在思考如何利用 Laravel,更进一步做出一套较为不一样的开发框架出来。反复看了很多有关 Laravel 框架的资料和文档,最后还是落在 Larave...

982
来自专栏Java帮帮-微信公众号-技术文章全总结

大文件拆分方案的Java实践【面试+工作】

大文件拆分问题涉及到io处理、并发编程、生产者/消费者模式的理解,是一个很好的综合应用场景,为此,花点时间做一些实践,对相关的知识做一次梳理和集成,总结一些共性...

2964

扫码关注云+社区

领取腾讯云代金券