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


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

   在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来进行对比:
 首先是注册:
 
   其次是事件通知:
   
    最后就是收到事件通知后的事件处理了:
     

  

 Demo资源地址 地址2

不过瘾?不要紧,下面有更好的事件通知工具:

GitHub项目地址

   

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xuexiangjys

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值