Java观察者模式里面主要有两个角色:主题(Subject)和观察者(Observer/Listener)。关心某主题的人,都可以说是这个主题的观察者。他们关心主题的变化,当变化发生时,观察者会被自动通知到然后做出相应的动作。举个最贴切的例子:产品的需求说明是程序猿都关心的,当PM说需求说明发生变化的时候,程序猿就要修改代码去实现新的需求。这里,需求说明就是主题,程序猿就是观察者。下面,用代码来具体说明观察者模式是怎样工作的。
首先,定义一个观察者的接口ReqObserver:
public interface ReqObserver {
public void update();
}
为了简单,里面只有一个update()方法。关心产品需求的程序猿将实现这个接口。接着,再看看需求说明Requirement:
public class Requirement {
public List<ReqObserver> listeners = new ArrayList<ReqObserver>();
public void requirementChanged () {
System.out.println("PM: 亲们,需求改了啊!");
notifyObserver();
}
public void notifyObserver () {
for (ReqObserver r: listeners) {
r.update();
}
}
public void addListener (ReqObserver r) {
listeners.add(r);
}
public void removeListener (ReqObserver r) {
listeners.remove(r);
}
}
其主要的功能是,当有改变发生时,就调用notifyObserver()方法通知观察者去做更新。需要通知的观察者都保存在listeners的列表里。方法addListener()和removeListener()用来增加和删除需用通知的观察者。
下面再看看实现ReqObserver接口的程序猿ProgrammerA和ProgrammerB:
public class ProgrammerA implements ReqObserver {
public ProgrammerA (Requirement req) {
req.addListener(this);
}
@Override
public void update() {
// do something
System.out.println("ProgrammerA: 擦, 需求又改了。。。");
}
}
public class ProgrammerB implements ReqObserver {
public ProgrammerB (Requirement req) {
req.addListener(this);
}
@Override
public void update() {
// do something
System.out.println("ProgrammerB: 尼玛,又要加班了。。。");
}
}
这样,主题和观察者都建立好了。最后,写一个简单的主函数来执行一下:
public class ExampleProject {
public static void main(String[] args) {
Requirement req = new Requirement();
ProgrammerA a = new ProgrammerA(req);
ProgrammerB b = new ProgrammerB(req);
req.requirementChanged();
}
}
执行结果如下:
PM: 亲们,需求改了啊!
ProgrammerA: 擦, 需求又改了。。。
ProgrammerB: 尼玛,又要加班了。。。
我们可以看到,主函数里程序猿a和b并没有直接调用update()方法,但是当需求发生改变requirementChanged()被调用时,他们自动作出了反应,这就是观察者模式的魅力所在。