觀察者模式:定義對象之間的一種一對多的依賴關係,當一個對象狀態發生改變時,所有依賴於他的對象都將得到通知並自動更新。
下面通過該模式思想來實現一個事件機制。某個業務狀態變更時發出具體事件,有需要的業務監聽該業務事件,並在監聽到事件時做出反應處理。
首先定義抽象事件接口,包括髮布事件、註冊事件監聽器、註銷事件監聽器等事件操作,併發布服務。
/**
* 事件抽象接口
* &&
* 提供事件發佈以及事件監聽器的註冊、刪除方法
* @author xx
*/
public interface EventService
{
/**
* 發佈事件
* @param event 事件
*/
public void publish(Event event);
/**
* 批量發佈事件
* @param collection 事件集合
*/
public void publish(Collection<Event> collection);
/**
* 註冊事件監聽
* @param eventListener 事件監聽器
* @param eventID 事件ID
*/
public void addEventListener(EventListener eventListener, String eventID);
/**
* 註冊事件監聽,根據 filter 過濾
* @param eventListener 事件監聽器
* @param filter 過濾器
* @param eventID 事件ID
*/
public void addEventListener(EventListener eventListener, EventFilter filter, String eventID);
/**
* 註銷事件監聽
* @param eventListener 事件監聽器
*/
public void removeEventListener(EventListener eventListener);
}
其中,Event是抽象事件類,包含基本的事件id,事件資源等屬性,所有具體事件繼承該類;EventListener爲抽象事件監聽器接口,所有具體事件監聽器繼承該接口;EventFilter爲事件過濾接口。
EventListener定義如下:
/**
* 事件監聽器抽象接口,所有具體事件監聽器繼承該接口
* @author xx
*
*/
public interface EventListener
{
/**
* 事件監聽器處理方法
* @param event 事件
*/
public void onEvent(Event event);
}
然後,發佈事件的業務可以定義自己的具體事件對象,如下,
/**
* 測試事件,繼承自抽象事件
* @author xx
*
*/
public class TestEvent extends Event
{
/**
* 序列號
*/
private static final long serialVersionUID = 2107606925118238578L;
/**
* 事件類型,可以是個枚舉,這裏測試不再具體定義
*/
private String eventType;
/**
* 事件數據列表,測試,不再具體定義
*/
private List<Object> objList = new ArrayList<Object>();
public String getEventType()
{
return eventType;
}
public void setEventType(
String eventType)
{
this.eventType = eventType;
}
public List<Object> getObjList()
{
return objList;
}
public void setObjList(List<Object> objList)
{
this.objList = objList;
}
}
並在狀態發生變更的時候,發佈事件
/**
* 測試事件發佈類
* @author xx
*
*/
public class TestEventPublisher
{
private EventService eventService;
public void publicTestEvent()
{
TestEvent event = new TestEvent();
event.setEventType("testType");
//構造數據等代碼省略
eventService.publish(event);
}
public EventService getEventService()
{
//測試代碼,省掉具體獲取服務方法
return eventService;
}
public void setEventService(EventService eventService)
{
this.eventService = eventService;
}
}
然後,和該業務相關的業務監聽該業務事件,定義一個抽象事件類,通過一個事件隊列,在業務內部管理事件,當監聽到事件時,加入事件隊列,併爲每個事件建立線程任務,通過該隊列將事件分發出去處理。
/**
* 業務事件監聽器抽象類
* @author xx
*
*/
public abstract class AbstractEventListener implements IEventListener
{
/**
* 事件隊列
*/
private BlockingQueue<Event> eventQueue = new LinkedBlockingQueue<Event>();
/**
* 事件監聽狀態
*/
private AtomicBoolean isRunning = new AtomicBoolean(true);
/**
*啓動事件監聽
*/
@Override
public void start()
{
ThreadFactory.getInstance().startThread(new EventHandler());
}
public void onEvent(Event event)
{
try
{
//新增事件加入事件隊列
eventQueue.put(event);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
/**
* 停止事件監聽
*/
@Override
public void stop()
{
isRunning.compareAndSet(true, false);
}
private class EventHandler implements Runnable
{
@Override
public void run()
{
try
{
while(isRunning.get())
{
//從事件隊列取出事件執行
process(eventQueue.take());
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
其中,IEventListener是該業務自己的監聽接口,繼承自基本監聽接口EventListener
/**
* 業務事件監聽接口,繼承自基本事件監聽接口
* @author xx
*
*/
public interface IEventListener extends EventListener
{
/**
* 事件處理方法
* @param event 事件
*/
public void process(Event event);
/**
* 啓動事件監聽
*/
public void start();
/**
* 停止事件監聽
*/
public void stop();
}
當然,該業務還沒有註冊事件監聽器,這樣當發佈事件的業務發佈事件時候,你也是收不到的,定義一個事件管理類,負責註冊事件
/**
* 業務事件監聽管理類
* @author xx
*
*/
public class EventMonitor
{
/**
* 事件管理服務
*/
private EventService eventService;
/**
* 測試用事件監聽器
*/
private IEventListener testEventListener;
private void registerListeners()
{
//註冊測試事件監聽器
eventService.addEventListener(testEventListener, "testEventId");
}
private void unregisterListeners()
{
//註銷事件監聽器
eventService.removeEventListener(testEventListener);
}
/**
* 綁定服務
* @param service 服務
* @param properties 屬性
*/
public void bindService(Object service, Map<Object, Object> properties)
{
if(service instanceof EventService)
{
eventService = (EventService)service;
registerListeners();
}
else
{
;
}
}
/**
* 解綁定服務
* @param service 服務
* @param properties 屬性
*/
public void unbindService(Object service, Map<Object, Object> properties)
{
if(service instanceof EventService)
{
eventService = null;
unregisterListeners();
}
else
{
;
}
}
public EventService getEventService()
{
return eventService;
}
public void setEventService(
EventService eventService)
{
this.eventService = eventService;
}
public IEventListener getTestEventListener()
{
return testEventListener;
}
public void setTestEventListener(IEventListener testEventListener)
{
this.testEventListener = testEventListener;
}
}
通過spring.xml中配置服務監聽,綁定EventService服務,在系統啓動是回調綁定方法bindService,並註冊事件監聽器,具體配置如下:
<!--監聽EventService服務,並通過綁定的方式注入服務-->
<oms:reference id="eventService" interface="base.event.EventService" wait="false">
<oms:listener ref="Event_Service" bind-method="bindService" unbind-method="unbindService"/>
</oms:reference>
<!--通過依賴注入實例化EventMonitor中的具體監聽器屬性-->
<bean id="Event_Service" class="service.event.EventMonitor">
<property name="testEventListener" ref="Test_Event_Service">
</bean>
<!--註冊實例化回調方法來啓動監聽器-->
<bean id="Test_Event_Service" class="service.event.TestEventListener"
init-method="start" destroy-method="stop">
</bean>
事件監聽器如下:
/**
* 一個具體的事件監聽器
* @author xx
*
*/
public class TestEventListener extends AbstractEventListener
{
@Override
public void process(Event event)
{
//非指定具體事件不處理
if(event instanceof TestEvent)
{
return;
}
final TestEvent testEvent = (TestEvent)event;
//過濾事件類型
if(testEvent.getEventType().equals("testType"))
{
//處理事件
processEvent(event);
}
}
private void processEvent(Event event)
{
// TODO Auto-generated method stub
}
}
通過以上操作,就說明整個事件機制,在自己的業務中可以註冊所有需要的事件,而發佈事件的業務只需要將自己的狀態變換通過事件發佈出去,很好的實現了模塊之間的解耦。