Observer Pattern 是一种常用的设计模式,它是一种事件监听模型。该模式有两个角色,一个是Subject, 另一个是Observer。Subject 保存有多个Observer的引用,一旦特定的事件发生,Subject会通知它所有的Observer,Observer得到该通知后执行相关程序逻辑。其中,Observer只有先向Subject注册后才能被Subject知晓。这就像订报纸,只有我们向出版社提出订报的申请,出版社才会把我们列入订阅者名单,然后每当新报纸印好时,出版社会通知订阅者取报纸。这里订阅的用户就是 Observer, 出版社即 Subject。
Subject , Observer的类图如下:
下面通过一个实例来体会一下观察者模式。
公司需要招聘人才时,往往会去找猎头(headhunter)。猎头知道很多求职者(applicant)的联系方式,一旦有公司招人,猎头就会给这些求职者打电话,以通过他们有工作可以做了。在这里面,猎头就是 Subject,求职者就是 Observer。
我们来实现这样一个功能。设计两个类,HeadHunter 和 Applicant,分别代表猎头和求职者。HeadHunter 类有一个属性 jobName,当jobName有新的值时(相当于公司要招人),HeadHunter 就通知他所知道的所有 Applicant 告诉他们有工作了。类图如下:
Subject 接口定义:
public interface Subject { void registerObjserver(Observer ob); void removeObserver(Observer ob); void notifyObservers(); }
public interface Observer { void update(Subject subject); }
public class HeadHunter implements Subject { private List<Observer> obList = new ArrayList<Observer>(); private boolean isNotify = true; private String jobName; /** * 注册一个Observer */ @Override public void registerObjserver(Observer ob) { obList.add(ob); } /** * 移除一个Observer */ @Override public void removeObserver(Observer ob) { obList.remove(ob); } /** * 通知所有的Observer */ @Override public void notifyObservers() { if (true == isNotify) { performNotify(); isNotify = false; } } /** * 添加一个新的工作。添加完成后马上通知所有Observer * @param jobName */ public void setJobName(String jobName) { this.jobName = jobName; isNotify = true; notifyObservers(); } private void performNotify() { for (Observer ob : obList) { ob.update(this); } } public String getJobName() { return jobName; } }
public class Applicant implements Observer { private String name; public Applicant(String name) { this.name = name; } @Override public void update(Subject subject) { HeadHunter h = (HeadHunter)subject; out.println(name + "收到通知:" + h.getJobName()); } }
这个小程序的功能是,一旦 HeadHunter 的 setJobName() 方法被调用(即有新工作),HeadHunter 马上通知它的 Applicant 告诉他们有工作了。程序测试代码如下:
public static void main(String[] args) { HeadHunter hh = new HeadHunter(); // 注册observer hh.registerObjserver(new Applicant("张三")); hh.registerObjserver(new Applicant("李四")); hh.registerObjserver(new Applicant("王五")); // 添加一个job // 此时所有observer的update()方法都会被调用 hh.setJobName("Java程序员"); }
Observer Pattern 在Swing中应用非常广泛,比如调用 JButton 的 addListener() 添加一个事件监听器,此时 JButton 就是 Subject, Listener 就是 Observer。由于观察者模式比较常用,所以需要我们好好体会掌握。