在设计模式中,观察者模式,通常又称为发布/订阅(Publish/Subscribe)模式,举个例子来理解,
1、有一个报社
2、你订阅了这家报社的报纸
3、报社每次出新报纸就会给你送一份
当然,如果你不想再收到这些报纸了,只需要给报社打个电话取消你的订阅就可以,这其实就是一个观察者模式,也叫做发布订阅模式。报社是被观察者,也叫做发布者,“你”是一个观察者,也叫做订阅者。
在通过一个老师学生的例子来举例
有一个老师,他有一群学生,现在他需要将这些学生的考试成绩通知给他们,如何来实现呢?
首先来分析,老师通知学生,所以老师是发布者, 学生接收老师通知,是订阅者。
老师有一个行为,那就是通知学生成绩。
学生也有一个行为,那就是接收老师的通知。
这里有一个和报社发报纸的例子不一样的地方,那就是每个学生的成绩是不一样的,而且为了保护学生,我们不希望学生的成绩会被其他人知道。
ok,有了这些分析基本就可以开始写代码了
首先,我们需要先定义两个接口,一个是被观察者(发布者),一个是观察者(订阅者)
/** * 主题接口,即被观察者接口 * @author liuyck * */ public interface Subject { /** * 添加观察者 * @param id 观察者id * @param obj 观察者本身对象 */ void addObserver(String id, Observer obj); /** * 移除观察者 * @param id 观察者id */ void deleteObserver(String id); /** * 当主题方法改变时,这个方法被调用,通知所有的观察者 * @param msg 通知消息 */ void notifyObservers(Object msg); /** * 当主题方法改变时,这个方法被调用,通知指定观察者 * @param id 观察者id * @param msg 通知消息 */ void notifyObserver(String id,Object msg); }
/** * 观察者接口 * @author liuyck * */ public interface Observer { /** * 当主题状态改变时,观察者更新数据 * @param msg */ void update(Object msg); }
被观察者接口具有添加观察者、删除观察者、通知所有观察者、通知指定观察者的行为。
观察者接口具有更新数据的行为。
接口订好了,下面就是具体实现了。
老师的实现
/** * 老师类 * @author liuyck * */ public class TeacherSubject implements Subject{ /** * 学生Map */ private Map<String, Observer> observerMap = new HashMap<String, Observer>(); @Override public void addObserver(String id, Observer obj) { observerMap.put(id, obj); } @Override public void deleteObserver(String id) { observerMap.remove(id); } @Override public void notifyObservers(Object msg) { // TODO Auto-generated method stub } @Override public void notifyObserver(String id, Object msg) { observerMap.get(id).update(msg); } }
学生的实现
/** * 学生类 * @author liuyck * */ public class StudentObserver implements Observer{ private String name; /** * 每一个学生有一个唯一的名称和一位老师 * @param name * @param t */ public StudentObserver(String name,TeacherSubject t) { this.name=name; //每新建一个学生对象,默认添加到观察者的行列 t.addObserver(name, this); } @Override public void update(Object msg) { System.out.println("学生" + this.name + "收到消息:" + msg); } }
测试方法
/** * 老师学生观察者模式测试类 * @author liuyck * */ public class DemoTest { public static void main(String[] args) { TeacherSubject teacher = new TeacherSubject(); new StudentObserver("jack", teacher); new StudentObserver("john", teacher); teacher.notifyObserver("jack", "你考了99分"); teacher.notifyObserver("john", "你考了59分"); } }