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



相关文章
|
1天前
|
Java 开发者 Spring
Java Springboot监听事件和处理事件
通过这些内容的详细介绍和实例解析,希望能帮助您深入理解Spring Boot中的事件机制,并在实际开发中灵活应用,提高系统的可维护性和扩展性。
18 7
|
12天前
|
安全 算法 Java
Java CAS原理和应用场景大揭秘:你掌握了吗?
CAS(Compare and Swap)是一种乐观锁机制,通过硬件指令实现原子操作,确保多线程环境下对共享变量的安全访问。它避免了传统互斥锁的性能开销和线程阻塞问题。CAS操作包含三个步骤:获取期望值、比较当前值与期望值是否相等、若相等则更新为新值。CAS广泛应用于高并发场景,如数据库事务、分布式锁、无锁数据结构等,但需注意ABA问题。Java中常用`java.util.concurrent.atomic`包下的类支持CAS操作。
43 2
|
2月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
2月前
|
缓存 Java 开发者
Java多线程并发编程:同步机制与实践应用
本文深入探讨Java多线程中的同步机制,分析了多线程并发带来的数据不一致等问题,详细介绍了`synchronized`关键字、`ReentrantLock`显式锁及`ReentrantReadWriteLock`读写锁的应用,结合代码示例展示了如何有效解决竞态条件,提升程序性能与稳定性。
160 6
|
1月前
|
监控 Java 数据库连接
Java线程管理:守护线程与用户线程的区分与应用
在Java多线程编程中,线程可以分为守护线程(Daemon Thread)和用户线程(User Thread)。这两种线程在行为和用途上有着明显的区别,了解它们的差异对于编写高效、稳定的并发程序至关重要。
37 2
|
2月前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
56 2
|
5天前
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
|
2月前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
4月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
2月前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###