技术问答-24 如何实现观察者模式
一、Java实现观察者模式 用java提供的Observable Observer:
package com;import java.util.Observable;import java.util.Observer;/** * 被通知的对象 * @author Administrator * */public class User implements Observer {private String name;public User(String name) {this.name = name;}public void update(Observable o, Object arg) { System.out.println("抢票用户"+name + arg+"有票了:");}}
package com;import java.util.Observable;/** * 被观察者 * @author Administrator * */public class OfficialAccount extends Observable {public void publishNewInfo(String info) {setChanged();notifyObservers(info);}}
package com;/** * 测试 * @author Administrator * */public class Test {public static void main(String[] args) {// 被观察的角色 OfficialAccount officialAccount = new OfficialAccount();// 观察者 User userliu = new User("小刘"); User userli = new User("小李"); User userbai = new User("小白");// 将观察者注册到可观察对象的观察者列表中 officialAccount.addObserver(userliu); officialAccount.addObserver(userli); officialAccount.addObserver(userbai);// 发布消息 officialAccount.publishNewInfo("k123");//小刘抢了k123 不用再抢了 officialAccount.deleteObserver(userliu);// officialAccount.publishNewInfo("D345");}}
二、观察者模式解释
观察者模式:有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式,是软件设计模式的一种
在此种模式中,一个目标物件管理所有相依于它的观察者物件(说白了就是我被观察了 我还得管着观察我的人 真心累!),
被观察者本身的状态改变时主动发出通知(你望远镜看着我 我动了一下 我还要打电话告诉你 我动了! )。
被观察者通常通过调用各观察者所提供的方法来实现(我 需要打你电话 还得是你的电话号码)。
此种模式通常被用来实现事件处理系统
三、 自己实现观察者模式
我的总结:观察者模式就是 被观察的人把所有观察他的人存起来 一旦自己状态变了之后 就挨个通知观察他的人
自己写一个的话 就是
一个被观察者类 (1) 存储所有他的观察者 (2)状态改变方法 (3) 通知观察者方法
一个观察者类 (1) 有一个方法 给被观察者调用
package com;/** * 观察者 * * @author Administrator * */public class Guancha {public Guancha(String name) {this.name = name;}private String name;/** * 这是一个被调用的方法 当被观察者状态变化之后 就会调用所有他的观察者的这个方法 */public void update(String str) { System.out.println(name + ":收到被观察者的通知! " + "被观察者状态:" + str);}}
package com;import java.util.ArrayList;import java.util.List;/** * 被观察者 * * @author Administrator * */public class BeiGuancha {// 被观察者的状态private String state;// 存储他所有的观察者 List<Guancha> guanchazhes;public BeiGuancha() { guanchazhes = new ArrayList<Guancha>();}// 添加观察者public void addGuancha(Guancha g) { guanchazhes.add(g);}// 通知所有观察者public void notifyAllGuancha() {for (Guancha g : guanchazhes) { g.update(state);}}public String getState() {return state;}public void setState(String state) {this.state = state;}}
package com;/** * 测试 * * @author Administrator * */public class Test {public static void main(String[] args) {// 新建观察者 Guancha g1 = new Guancha("打不死小强"); Guancha g2 = new Guancha("没对象小明");// 新建被观察者 添加他的观察者 BeiGuancha bgc = new BeiGuancha(); bgc.addGuancha(g1); bgc.addGuancha(g2);// 修改被观察者状态 bgc.setState("修改009");// 通知观察者 状态变了 bgc.notifyAllGuancha();}}
四、用事件委托实现观察者模式
我理解的所谓的事件委托实现 就是不让被观察者直接接触观察者(怕打架??)
而是通过一个中间人(Event) 如果被观察者需要通知观察者的话 就告诉Event 然后Event在去通知观察者 这里会用到反射
为什么会用到反射呢 Event存储了观察者对象 和 方法名 到使用的时候 是动态调用的~~
package com;/** * 观察者 * * @author Administrator * */public class Guancha {public Guancha(String name) {this.name = name;}private String name;/** * 这是一个被调用的方法 当被观察者状态变化之后 就会调用所有他的观察者的这个方法 */public void update(String str) { System.out.println(name + ":收到被观察者的通知! " + "被观察者状态:" + str);}}
package com;import java.lang.reflect.Method;/** * Event 他就是把观察者跟被观察者隔离了 也就相当于是代理 * @author Administrator * */public class Event {// 观察者private Object object;// 方法名private String methodName;// 方法参数 我觉得 这个应该是在被观察者调用的时候才设置值的(也就是说Event的invoke方法传进来的参数)private Object[] params;// 方法参数类型private Class[] paramTypes;public Event(Object object, String methodName, Class... paramTypes) {this.object = object;this.methodName = methodName;this.paramTypes = paramTypes;}/* * 执行该对象的该方法 */public void invoke(Object... args) {try {// 设置参数this.params = args; Method method = object.getClass().getMethod(methodName, paramTypes);if (null == method) {return;} method.invoke(object, params);} catch (Exception e) { e.printStackTrace();}}}
package com;import java.util.ArrayList;import java.util.List;/** * 被观察者 * * @author Administrator * */public class BeiGuancha {// 被观察者的状态private String state;// 存储他所有的观察者 List<Event> events;public BeiGuancha() { events = new ArrayList<Event>();}// 添加观察者public void addGuancha(Event g) { events.add(g);}// 通知所有观察者public void notifyAllGuancha() {for (Event e : events) { e.invoke(state);}}public String getState() {return state;}public void setState(String state) {this.state = state;}}
package com;/** * 测试 * * @author Administrator * */public class Test {public static void main(String[] args) {// 新建观察者 Guancha g1 = new Guancha("打不死小强"); Guancha g2 = new Guancha("没对象小明");// 新建被观察者 添加他的观察者 BeiGuancha bgc = new BeiGuancha(); bgc.addGuancha(new Event(g1, "update", new Class[]{String.class})); bgc.addGuancha(new Event(g2, "update", new Class[]{String.class}));// 修改被观察者状态 bgc.setState("修改009");// 通知观察者 状态变了 bgc.notifyAllGuancha();}}