設計模式之觀察者模式

           觀察者模式:定義對象之間的一種一對多的依賴關係,當一個對象狀態發生改變時,所有依賴於他的對象都將得到通知並自動更新。

    下面通過該模式思想來實現一個事件機制。某個業務狀態變更時發出具體事件,有需要的業務監聽該業務事件,並在監聽到事件時做出反應處理。

    首先定義抽象事件接口,包括髮布事件、註冊事件監聽器、註銷事件監聽器等事件操作,併發布服務。

                

/**
 * 事件抽象接口
 * &&
 * 提供事件發佈以及事件監聽器的註冊、刪除方法 
 * @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
		
	}

}

    通過以上操作,就說明整個事件機制,在自己的業務中可以註冊所有需要的事件,而發佈事件的業務只需要將自己的狀態變換通過事件發佈出去,很好的實現了模塊之間的解耦。

 



 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章