Java设计模式之观察者模式的应用--简单的事件通知工具

简介: Java设计模式之观察者模式的应用--简单的事件通知工具

相信大家对“观察者模式”应该都很熟悉,不熟的可以自行百度。今天我主要介绍的就是如何将“观察者模式”的设计思想运用到实际的工程中去,实现一个简单的事件通知工具。


  在Android中,对于事件的处理有很多,广播broadcast就是一个非常轻量的机制。广播用起来非常方便,比起接口来说好用很多。但是,广播如果使用不当的话,很有可能出现牵一发而动全身的效果,而且代码的可阅读性也比较差。那么废话不多说,我开始介绍今天要实现的简单的事件通知工具。


URM图如下图所示:

20161106172141666.png


 这是一个简单的纯传递事件的事件传递机制,不支持传递数据。实现原理:IObserver是观察者(订阅者)的实现接口,ISubject是被观察者(被订阅者)的实现接口,他们中间通过EventManager来进行统一管理和协调。实现的代码如下:


package com.xuexiang.util.observer.normal;
import java.util.HashMap;
import java.util.Map;
/**  
 * 创建时间:2016-6-5 上午1:12:48  
 * @author xuexiang
 **/
public class EventManager {
  /**
   * 存放所有被观察者对象的集合
   */
  private static Map mEventManager = new HashMap();  //存放各种被观察者对象
  /**
   * 获取被观察者对象
   * @param subjectName 被观察者对象的标记
   */
  public static BaseSubject getSubject(String subjectName) {
    BaseSubject baseSubject;
    if (mEventManager.containsKey(subjectName)) {
      baseSubject = mEventManager.get(subjectName);
    } else {
      baseSubject = new BaseSubject();
      mEventManager.put(subjectName, baseSubject);
    }
    return baseSubject;
  }
}
package com.xuexiang.util.observer.normal;
/**  
 * 被观察者接口
 * 创建时间:2016-6-5 上午1:00:25  
 * @author xuexiang
 **/
public interface ISubject {
  /**
   * 增加观察者
   * @param observer 实现IObserver接口的对象
   */
  public void register(IObserver observer);
  /**
   * 删除观察者
   * @param observer 实现IObserver接口的对象
   */
  public void unregister(IObserver observer);
  /**
   * 通知所有的观察者
   */
  public void notifyObservers();
}
package com.xuexiang.util.observer.normal;
/**  
 * 观察者接口
 * 创建时间:2016-6-5 上午12:55:56  
 * @author xuexiang
 **/
public interface IObserver {
   public void onChanged();
   public void onInvalidated();
}
package com.xuexiang.util.observer.normal;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
/**  
 * 被观察者
 * 创建时间:2016-6-5 上午1:03:27   
 * @author xuexiang
 **/
public class BaseSubject implements ISubject {
    /**
     * 存放数据观察者集合
     */
    private ArrayList<WeakReference> mObservers = new ArrayList<WeakReference>();
  @Override
  public void register(IObserver observer) {
    WeakReference obs = new WeakReference(observer);
    mObservers.add(obs);
  }
  @Override
  public void unregister(IObserver observer) {
    WeakReference obs = new WeakReference(observer);
    mObservers.remove(obs);
  }
  @Override
  public void notifyObservers() {
    ArrayList<WeakReference> observers = mObservers;
      int count = observers.size();
    for (int i = count - 1; i >= 0; i--) {
      WeakReference weak = observers.get(i);
      IObserver obs = weak.get();
      if (obs != null) {
        obs.onChanged();
      } else {
        observers.remove(i);
      }
    }
  }
}


   也许只是单纯的传递事件还不够,那么下面我来给大家介绍支持数据传递的工具。


 URM图如下图所示:


20161106180848326.png


  这是一个简单的纯传递事件的事件传递机制,支持传递数据,支持多事件的传递。实现原理:ITagObserver是观察者(订阅者)的实现接口,ITagSubject是被观察者(被订阅者)的实现接口,与上文不同的是,在注册观察者的时候,需要额外定义注册的事件Tag,且被观察者通知事件变化的时候,可以传递一个Event对象,通过该对象传递数据。这里注册的事件Tag就类比广播里面的Action,Event就类比广播里面的Intent,他们中间通过TagEventManager来进行统一管理和协调。实现的代码如下:

 

package com.xuexiang.util.observer.tag;
import java.util.HashMap;
import java.util.Map;
/**  
 * 创建时间:2016-6-5 下午4:16:29  
 * @author xuexiang
 **/
public class TagEventManager {
  private static Map mEventManager = new HashMap();  //存放各种被观察者对象
  public static BaseTagSubject getTagSubject(String subjectName) {
    BaseTagSubject baseSubject;
    if (mEventManager.containsKey(subjectName)) {
      baseSubject = mEventManager.get(subjectName);
    } else {
      baseSubject = new BaseTagSubject();
      mEventManager.put(subjectName, baseSubject);
    }
    return baseSubject;
  }
}
package com.xuexiang.util.observer.tag;
import java.util.List;
/**  
 * 创建时间:2016-6-5 下午2:17:04  
 * @author xuexiang
 **/
public interface ITagSubject {
  /**
   * 增加观察者
   * @param observer 实现ITagObserver接口的对象
   * @param eventTagList 注册事件标志的集合
   */
  public void register(ITagObserver observer, List eventTagList);
  /**
   * 删除观察者
   * @param observer 实现ITagObserver接口的对象
   */
  public void unregister(ITagObserver observer);
  /**
   * 通知符合要求的观察者
   * @param event 同时的具体事件
   */
  public void notify(Event event);
}
package com.xuexiang.util.observer.tag;
/**  
 * 创建时间:2016-6-5 下午2:24:22  
 * @author xuexiang
 **/
public interface ITagObserver {
   public void onChanged(Event event);
}
package com.xuexiang.util.observer.tag;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**  
 * 创建时间:2016-6-5 下午2:15:25   
 * @author xuexiang 
 **/
public class BaseTagSubject implements ITagSubject {
  //存放数据观察者集合
    private Map<WeakReference, List> mObservers = new HashMap<WeakReference, List>();
  @Override
  public void register(ITagObserver observer, List event ) {
    WeakReference obs = new WeakReference(observer);
    mObservers.put(obs, event);
  }
  @Override
  public void unregister(ITagObserver observer) {
    WeakReference obs = new WeakReference(observer);
    mObservers.remove(obs);
  }
  @Override
  public void notify(Event event) {
     Iterator<Map.Entry<WeakReference, List>> it = mObservers.entrySet().iterator();
     while (it.hasNext()) {
       Map.Entry<WeakReference, List> entry = it.next();
       WeakReference weak = entry.getKey();
       List eventTagList = entry.getValue();
       ITagObserver obs = weak.get();
       if (obs != null) {
        for (String tag : eventTagList) {
        if (event.getTag().equals(tag)) {
          obs.onChanged(event);
        }
        }       
      } else {
        it.remove();
      }
    }
  }
}
package com.xuexiang.util.observer.tag;
/**  
 * 创建时间:2016-6-5 下午2:18:06  
 * @author xuexiang
 **/
public class Event {
    private String mTag;
    private String mMessage;
  /**
   * @param tag 消息事件标志
   * @param msg 消息事件内容
   */
  public Event (String tag, String msg) {
    mTag = tag;
    mMessage = msg;
  }
  public String getTag() {
    return mTag;
  }
  public String getMessage() {
    return mMessage;
  }
}


 那么如何使用呢?我们将其和当下最流行的EventBus来进行对比:

首先是注册:


20161107090015305.png


 其次是事件通知:


20161107090217902.png


  最后就是收到事件通知后的事件处理了:


20161107090429311.png



相关文章
|
8天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
17天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
10天前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
24 3
|
20天前
|
SQL 监控 Java
技术前沿:Java连接池技术的最新发展与应用
本文探讨了Java连接池技术的最新发展与应用,包括高性能与低延迟、智能化管理和监控、扩展性与兼容性等方面。同时,结合最佳实践,介绍了如何选择合适的连接池库、合理配置参数、使用监控工具及优化数据库操作,为开发者提供了一份详尽的技术指南。
29 7
|
18天前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
32 3
|
18天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
35 2
|
19天前
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
12 1
|
20天前
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入理解与应用
【10月更文挑战第22天】 在软件开发中,设计模式是解决特定问题的通用解决方案。本文将通过通俗易懂的语言和实例,深入探讨PHP中单例模式的概念、实现方法及其在实际开发中的应用,帮助读者更好地理解和运用这一重要的设计模式。
15 1
|
23天前
|
移动开发 前端开发 JavaScript
java家政系统成品源码的关键特点和技术应用
家政系统成品源码是已开发完成的家政服务管理软件,支持用户注册、登录、管理个人资料,家政人员信息管理,服务项目分类,订单与预约管理,支付集成,评价与反馈,地图定位等功能。适用于各种规模的家政服务公司,采用uniapp、SpringBoot、MySQL等技术栈,确保高效管理和优质用户体验。
|
8天前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。