相信大家对“观察者模式”应该都很熟悉,不熟的可以自行百度。今天我主要介绍的就是如何将“观察者模式”的设计思想运用到实际的工程中去,实现一个简单的事件通知工具。
在Android中,对于事件的处理有很多,广播broadcast就是一个非常轻量的机制。广播用起来非常方便,比起接口来说好用很多。但是,广播如果使用不当的话,很有可能出现牵一发而动全身的效果,而且代码的可阅读性也比较差。那么废话不多说,我开始介绍今天要实现的简单的事件通知工具。
URM图如下图所示:
这是一个简单的纯传递事件的事件传递机制,不支持传递数据。实现原理: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图如下图所示:
这是一个简单的纯传递事件的事件传递机制,支持传递数据,支持多事件的传递。实现原理: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来进行对比:
首先是注册:
其次是事件通知:
最后就是收到事件通知后的事件处理了: