觀察者模式與java委托
- 所謂觀察者模式,指的某個狀態信息的改變,會影響其他一系列的操作,這時就可以將這些操作抽象化,同時創建一個類統一的管理和執行這些操作。把這些抽象出來的操作稱為觀察者類,而管理這些操作的類稱為通知者類,通知者類維護着一個觀察者類的集合,可以追加和刪除觀察者,同時可遍歷通知所有觀察者類執行操作。
- 觀察者模式的不足:雖然觀察者模式提取出了抽象類,讓類與類之間不互相依賴,共同依賴於抽象接口,這符合依賴倒轉原則,但他們仍然依賴着抽象接口,而且有些時候不能提取出抽象的觀察者(比如引用jar包)。
- java委托機制與觀察者模式:委托機制的實現不再需要提取觀察者抽象類,觀察者和通知者互不依賴。java利用反射即可實現,代碼實例如下:
事件類
package com.suski.delegate; import java.lang.reflect.Method; public class Event { private Object object; private String methodName; private Object[] params; private Class[] paramTypes; public Event(Object object,String method,Object...args) { this.object = object; this.methodName = method; this.params = args; contractParamTypes(this.params); } private void contractParamTypes(Object[] params) { this.paramTypes = new Class[params.length]; for (int i=0;i<params.length;i++) { this.paramTypes[i] = params[i].getClass(); } } public void invoke() throws Exception { Method method = object.getClass().getMethod(this.methodName, this.paramTypes);//判斷是否存在這個函數 if (null == method) { return; } method.invoke(this.object, this.params);//利用反射機制調用函數 } }
事件管理類
package com.suski.delegate; import java.util.ArrayList; import java.util.List; public class EventHandler { private List<Event> objects; public EventHandler() { objects = new ArrayList<Event>(); } public void addEvent(Object object, String methodName, Object...args) { objects.add(new Event(object, methodName, args)); } public void notifyX() throws Exception { for (Event event : objects) { event.invoke(); } } }
通知者抽象類
package com.suski.delegate; public abstract class Notifier { private EventHandler eventHandler = new EventHandler(); public EventHandler getEventHandler() { return eventHandler; } public void setEventHandler(EventHandler eventHandler) { this.eventHandler = eventHandler; } public abstract void addListener(Object object,String methodName, Object...args); public abstract void notifyX(); }
通知者具體實現類
package com.suski.delegate; public class ConcreteNotifier extends Notifier{ @Override public void addListener(Object object, String methodName, Object... args) { this.getEventHandler().addEvent(object, methodName, args); } @Override public void notifyX() { try { this.getEventHandler().notifyX(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
具體的觀察者類,不再需要抽象觀察者
package com.suski.delegate; import java.util.Date; public class WatchingTVListener { public WatchingTVListener() { System.out.println("watching TV"); } public void stopWatchingTV(Date date) { System.out.println("stop watching" + date); } } package com.suski.delegate; import java.util.Date; public class PlayingGameListener { public PlayingGameListener() { System.out.println("playing"); } public void stopPlayingGame(Date date) { System.out.println("stop playing" + date); } }
測試方法
package com.suski.delegate; import java.util.Date; public class Test { public static void main (String[] args) { Notifier goodNotifier = new ConcreteNotifier(); PlayingGameListener playingGameListener = new PlayingGameListener(); WatchingTVListener watchingTVListener = new WatchingTVListener(); goodNotifier.addListener(playingGameListener, "stopPlayingGame", new Date()); goodNotifier.addListener(watchingTVListener, "stopWatchingTV", new Date()); goodNotifier.notifyX(); } }