Publish/Subscribe模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 意图是解除耦合,让耦合的双方都依赖抽象,而不依赖具体.
1 2 3 4 5 6 7 8 9 package observer;public interface Observer { void update () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package observer;public class StockObserver implements Observer { private String name; private Subject subject; public void update () { System.out.println(subject.getState() + ": " + name + " 快别看股票了." ); } public StockObserver (String name, Subject subject) { this .name = name; this .subject = subject; } }
1 2 3 4 5 6 7 8 9 10 11 12 package observer;public class FootballObserver implements Observer { public void update () { System.out.println("停止看足球,继续工作." ); } }
1 2 3 4 5 6 7 8 9 10 11 12 package observer;public interface Subject { void attach (Observer observer) ; void detach (Observer observer) ; void notifyALL () ; String getState () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package observer;import java.util.LinkedList;import java.util.List;public class Secretary implements Subject { private List<Observer> observers = new LinkedList <Observer>(); public String state; public void attach (Observer observer) { observers.add(observer); } public void detach (Observer observer) { observers.remove(observer); } public void notifyALL () { for (Observer observer : observers) { observer.update(); } } public String getState () { return state; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package observer;public class Main { public static void main (String[] args) { Secretary secretary = new Secretary (); FootballObserver jack = new FootballObserver (); StockObserver lucy = new StockObserver ("lucy" , secretary); secretary.attach(jack); secretary.attach(lucy); secretary.detach(jack); secretary.state = "老板来了" ; secretary.notifyALL(); } }
事件委托 观察者模式的不足:
通知者还是要依赖抽象的观察者.
各个观察者的不同行为都命名为update,不符合实际.
每个update的参数都相同.
事件委托就是将方法作为对象 委托给通知者,而不关心其属对象是什么类型;方法的参数可以任意. 极大降低了耦合.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package com.think.reflect;import java.lang.reflect.Method;public class MyEvent { private Object object; private Method method; private Object[] paras; public MyEvent (Object object, Method method, Object[] paras) { this .object = object; this .method = method; this .paras = paras; } public Object getObject () { return object; } public void setObject (Object object) { this .object = object; } public Method getMethod () { return method; } public void setMethod (Method method) { this .method = method; } public Object[] getParas() { return paras; } public void setParas (Object[] paras) { this .paras = paras; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package com.think.reflect;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.LinkedList;import java.util.List;public class EventHandler { private List<MyEvent> observers = new LinkedList <MyEvent>(); public void band (Object object, String strMethod, Object... paras) { try { Method method = object.getClass().getMethod(strMethod, constrainTypes(paras)); MyEvent myEvent = new MyEvent (object, method, paras); observers.add(myEvent); } catch (NoSuchMethodException e) { e.printStackTrace(); } } public void notifyALL () { for (MyEvent myEvent : observers) { try { myEvent.getMethod().invoke(myEvent.getObject(), myEvent.getParas()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } private Class[] constrainTypes(Object[] paras) { if (paras == null ) return null ; Class[] paraTypes = new Class [paras.length]; int i = 0 ; for (Object object : paras) { paraTypes[i++] = object.getClass(); } return paraTypes; } }
1 2 3 4 5 6 7 8 9 10 11 package com.think.reflect;public class A { public void shut () { System.out.println("boss come, a" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 package com.think.reflect;public class B { public void wake (Integer time, String name) { System.out.println("boss come, b " + time + " " + name); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.think.reflect;public class Main { public static void main (String[] args) { A a = new A (); B b = new B (); EventHandler bossComeEventHandler = new EventHandler (); bossComeEventHandler.band(a, "shut" ); bossComeEventHandler.band(b, "wake" , 1 , "小明" ); bossComeEventHandler.notifyALL(); } }