昨天看《Java并发编程实例》时看到发布与逸出,看到他给出的隐式的使this引用逸出这一段示例代码时,就有种怪怪的感觉,查找之后发现是用观察者模式写的。
书中给的源码是:
public class ThreadEscape{
public ThreadEscape (EventSource source){
source.registerEvent(
new EventListerner(){
public void onEvent(Event e){
dosomething(e);
}
}):
}
}
我不知道有多少人是像我这样对设计模式并不了解的人就直接看这本书了。反正我是看这段代码看的晕乎乎的,所以我就先去看什么是观察者模式,接下来是我弄懂这段代码的全部过程:
首先,观察者模式:对象之间存在一对多关系,其中有一个主题,多个观察者,当作为主题的这个对象改变状态的时候,所有与之对应的观察者都会收到通知,并自动更新。上述的监听事件就是一个观察者模式的实现,在上面EventSource类就是一个主题,而EventListern就是它注册的一个观察者。
在这里我们提到了注册。秉着针对接口编程的思想,所以我们先会创建一个主题类所要实现的接口,在这个接口中我们首先肯定要有注册这个方法,当然有了注册,肯定也会需要有移出方法,毕竟当我们不想某一个观察者继续监听时,我们可以调用移出方法使它不再监听主题。
所以在这个时候我们可以编写出来的主题要实现的接口是这样的(这个模型我们就按照上面的事件监听来写):
public interface IEventSource{
public void registerEvent(IEventListerner listerner);
public void removeEvent(IEventListerner listerner);
public void notifyEvent();
}
在上面标红的地方,我们先从IEventListerner 来说,IEventListerner是观察者需要实现的接口。那么观察者们都需要实现的方法是什么呢?就是当主题状态发生改变后他们更新自己状态的方法,所以我们可以编写出观察者要实现的接口是这样的:
public interface IEventListerner{
public void onEvent(Event e);
}
那public void notifyEvent();又是起到什么作用?上面有说:当作为主题的这个对象改变状态的时候,所有与之对应的观察者都会收到通知。这个就是通知方法。所以在实现EventSource(主题的接口)时还需要一个sourceChange()方法。这时我们可以编写出一个主题类了:
public class EventSource impliments IEventSource{
private List<IEventListerner> events; // 用一个List来装所有已注册的观察者
private Event e; //改变的对象
public EventSource(){
event = new ArrayList<IEventListerner>();
}
public void registerEvent(IEventListener listener){
event.add(listerner);
}
public void removeEvent(IEventListener listener){
int i = event.indexOf(listener);
if(i>-1){
event.remove(i);
}
}
public void notifyEvent(){
for(int i = 0 ; i < event.size() ; i++){
EventListener el = (EventListener) event.get(i);
el.onEvent(e);
}
public void sourceChange(Event e){
this.e = e ;
notifyEvent(); //主题时状态一旦改变就通知所有观察者;
}
}
接着我们再来实现观察者的实现类:
public class EventListener impliments IEventListener {
public void onEvent(Event e){
进行相关操作....
}
其他方法......
}
现在,当我们调用sourceChange(Event e)时,依赖该主题的所有观察者都会发生状态上的改变。