本文共 7370 字,大约阅读时间需要 24 分钟。
观察者模式(发布-订阅模式):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
当一个对象的改变需同时改变其它对象的时候,而且它不知道具体有多少对象有待改变时,应考虑使用观察者模式。 优点: 第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表, 每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们 都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。 如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。 第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知. 缺点: 第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。 在使用观察者模式是要特别注意这一点。 第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。 第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使 观察者知道所观察的对象是怎么发生变化的。 第五、抽象通知者依赖于抽象观察者,没有抽象观察者的接口,通知功能就完成不了。另外就是每个具体 的观察者不一定是更新的方法update()要调用。
/** * 抽象观察者:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。 * 抽象观察者一般用一个抽象类或者一个接口实现,通常包含一个更新方法update()。 * */public abstract class Observer { public abstract void update(); }
/** * 具体观察者:实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。 * 具体观察者角色可以保存一个指向具体主题对象的引用。 */public class ConcreteObserver extends Observer { private String name; private String observerState; private ConcreteSubject subject; public ConcreteObserver(String name,ConcreteSubject subject){ this.name = name; this.subject = subject; } @Override public void update() { this.observerState = subject.getSubjectState(); System.out.println("观察者"+name+"的新状态是"+observerState); } public ConcreteSubject getSubject() { return subject; } public void setSubject(ConcreteSubject subject) { this.subject = subject; }}
/** * 主题或抽象通知者:一般用一个抽象类或一个接口实现,把所有对观察者对象的引用保存在一个聚集里, * 每个主题都可以有任何数量的观察者,可以增加或删除观察者对象。 */public abstract class Subject { private ListobserverList = new ArrayList (); //增加观察者 public void attach(Observer observer){ observerList.add(observer); } // 移除观察者 public void remove(Observer observer){ observerList.remove(observer); } // 通知 public void notice(){ for(Observer observer:observerList){ observer.update(); } }}
/** * 具体的主题或具体的通知者:将有关状态存入具体的观察者对象,在具体主题的内部状态改变时, * 给所有登记过的观察者发出通知。 */public class ConcreteSubject extends Subject { // 具体被观察者的状态 private String subjectState; public String getSubjectState() { return subjectState; } public void setSubjectState(String subjectState) { this.subjectState = subjectState; }}
public class Main { public static void main(String[] args) { // 主题对象(被观察者) ConcreteSubject subject = new ConcreteSubject(); // 添加观察者对象 subject.attach(new ConcreteObserver("X",subject)); subject.attach(new ConcreteObserver("Y",subject)); subject.attach(new ConcreteObserver("Z",subject)); // 主题对象状态更新 subject.setSubjectState("ABC"); // 发出通知 subject.notice(); }}
观察者模式实例:(老板-同事)
/** * 抽象观察者 * */public abstract class Observer { protected String name; // 对通知者的引用 protected Subject subject; public Observer(String name,Subject subject){ this.name = name; this.subject = subject ; } // 抽象更新方法 public abstract void update();}
/** * 看NBA的同事:具体的观察者,实现观察者抽象类 * */public class NBAObserver extends Observer { public NBAObserver(String name, Subject subject) { super(name, subject); } @Override public void update() { System.out.println(subject.getSubjectState() +" "+name+"关闭NBA直播,继继工作"); }}
/** * 看股票的同事:具体的观察者,实现观察者抽象类 * */public class StockObserver extends Observer { public StockObserver(String name, Subject subject) { super(name, subject); } @Override public void update() { System.out.println(subject.getSubjectState() +" "+name+"关闭股票行情,继继工作"); }}
/** * 通知者接口 */public interface Subject { // 添加观察者 public void attach(Observer observer); public void remove(Observer observer); // 通知者的状态 public String getSubjectState(); public void setSubjectState(String subjectState); // 发出通知 public void notice();}
/** * 老板:具体的通知者类,实现通知者接口 */import java.util.ArrayList;import java.util.List;public class Boss implements Subject { // 通知者的状态 private String subjectState; // 观察者的聚集 private ListobserverList = new ArrayList (); public void attach(Observer observer) { observerList.add(observer); } public String getSubjectState() { return subjectState; } public void remove(Observer observer) { observerList.remove(observer); } public void setSubjectState(String subjectState) { this.subjectState = subjectState; } // 发出通知 public void notice() { for(Observer observer:observerList){ observer.update(); } }}
public class Main { public static void main(String[] args) { // 老板胡汉三 Boss huhansan = new Boss(); // 看股票的同事 StockObserver tongshi1 = new StockObserver("小王",huhansan); // 看NBA的同事 NBAObserver tongshi2 = new NBAObserver("小李",huhansan); huhansan.attach(tongshi1); huhansan.attach(tongshi2); // 小李没有被老板通知到,所以移去 huhansan.remove(tongshi2); // 老板回来了 huhansan.setSubjectState("我胡汉三回来了"); // 发出通知 huhansan.notice(); }}
运行结果如下:
我胡汉三回来了 小王关闭股票行情,继继工作
观察者模式改进:利用委托机制对抽象通知者与抽象观察者依赖的解藕, 可指定不同的通知对象
和通知时调用不同的方法。
/** * 看NBA的同事:具体的观察者 * */public class NBAObserver { public void closeNBADirectSeeding(Date date) { System.out.println("关闭NBA直播,继继工作"+date); }}
/** * 看股票的同事:具体的观察者 * */public class StockObserver{ public void closeStockMarket(String name) { System.out.println("关闭股票行情,继继工作"+name); }}
/** * 事件类 */public class Event { // 要执行方法的对象 private Object object; // 要执行方法的名称 private String methodName; // 要执行方法的参数 private Object[] params; // 要执行方法的参数类型 private Class[] paramTypes; public Event(){ } public Event(Object object,String methodName,Object... args){ this.object = object; this.methodName = methodName; this.params = args; this.contractParamTypes(params); } // 根据参数数组生成参数类型数组 private void contractParamTypes(Object[] params){ this.paramTypes = new Class[params.length]; for(int i=0;i
/** * 若干Event类的载体,同时提供一个所有执行Event类的方法 * */public class EventHandler { private Listobjects; public EventHandler(){ objects = new ArrayList (); } // 添加某个对象要执行的事件,及需要的参数 public void addEvent(Object object,String methodName,Object... args){ objects.add(new Event(object,methodName,args)); } // 通知所有的对象执行指定的事件 public void notice() throws Exception{ for(Event event:objects){ event.invoke(); } }}
/** * 抽象通知者 * */public abstract class Subject { private EventHandler eventHandler = new EventHandler(); // 添加观察者 public abstract void addListener(Object object, String methodName,Object... args); // 通知所有观察者 public abstract void notice(); public EventHandler getEventHandler() { return eventHandler; } public void setEventHandler(EventHandler eventHandler) { this.eventHandler = eventHandler; }}
/** * 老板:具体的通知者类,实现通知者接口 */public class Boss extends Subject{ @Override public void addListener(Object object, String methodName, Object... args) { // 添加观察者对象 this.getEventHandler().addEvent(object, methodName, args); } @Override public void notice() { try { // 对所有观察者发出通知 System.out.println("老板回来了"); this.getEventHandler().notice(); } catch (Exception e) { e.printStackTrace(); } }}
/** * 观察者模式实例:利用委托机制对抽象通知者与抽象观察者依赖的解藕。 * 可指定不同的通知对象和通知时调用不同的方法。 */public class Main { public static void main(String[] args) { // 老板(也可以是前台放哨人) Boss boss = new Boss(); // 看NBA的同事 NBAObserver tongshi1 = new NBAObserver(); // 看股票的同事 StockObserver tongshi2 = new StockObserver(); // 添加被通知的对象 boss.addListener(tongshi1, "closeNBADirectSeeding", new Date()); boss.addListener(tongshi2, "closeStockMarket", "Test"); // 发出通知 boss.notice(); }}
运行结果如下:
老板回来了关闭NBA直播,继继工作Fri Jun 17 02:44:48 GMT 2011关闭股票行情,继继工作Test
转载地址:http://xyxmb.baihongyu.com/