什么是观察者模式:一个被观察者管理所有依赖他的观察者,在它自身发生状态改变时主动对所有观察者发出通知。
简单举个例子:报社订阅杂志这样一个行为。在这里报社就是被观察者,所有订阅了杂志的消费者就是观察者。报社一旦出了新杂志,变会给所有订阅了杂志的消费者快递杂志。
又或者开关和灯泡:一个开关是被观察者,他具有开和光两种行为。和他关联的灯泡就是观察者,当开关开时,所有建立了联系的灯泡就会亮,开关关时,所有建立了联系的灯泡就会灭。
下面展示如何通过代码实现这一关系:
首先创建一个观察者接口(一个具有阅读行为的读者接口):
public interface Reader {
void read();
}
接着创建一个被观察者接口(一个具有接受订阅,取消订阅,邮寄书籍行为的报社接口):
public interface NewspaperOffice {
void register(Reader reader);
void unregister(Reader reader);
void sendBooks();
}
接着我们来具体实现报社类,就用我小时候最爱的今古传奇武侠版来命名吧:
public class MartialArtsOffice implements NewspaperOffice{
private List<Reader> readers;
public MartialArtsOffice() {
readers=new ArrayList<Reader>();
}
@Override
public void register(Reader reader) {
readers.add(reader);
}
@Override
public void unregister(Reader reader) {
readers.remove(reader);
}
@Override
public void sendBooks() {
for(Reader reader:readers){
reader.read();
}
}
}
接着实现具体的读者类(因为大家都订阅的武侠杂志,所以我们实现一群武侠爱好者):
public class MartialArtsReader implements Reader {
private NewspaperOffice newspaperOffice;
public MartialArtsReader(NewspaperOffice newspaperOffice) {
this.newspaperOffice=newspaperOffice;
newspaperOffice.register(this);
}
@Override
public void read() {
System.out.println("这个月出的武侠故事真好看!");
}
}
最后我们实现看看是否成功:
public class Begin {
public static void main(String[] args) {
MartialArtsOffice martialArtsOffice=new MartialArtsOffice();
//小明通过构造方法订阅了杂志
MartialArtsReader xiaoming=new MartialArtsReader(martialArtsOffice);
//小红通过构造方法订阅了杂志
MartialArtsReader xiaohong=new MartialArtsReader(martialArtsOffice);
//杂志社给订阅了杂志的人们发送杂志
martialArtsOffice.sendBooks();
}
}
总结:观察者模式实质上就是一个被观察者持有一个观察者的集合,并且为观察者提供了将自己加入和移除集合的方法(订阅和取消订阅),以及通知所有观察者的方法(通过遍历集合调用观察者的共有行为,代码中的read());
而观察者则持有一个被观察者,调用其方法将自身加入进去。并且提供一个共有的行为方法供被观察者调用。
其实就是相互持有的一个状态。
这里面我们的实现都是通过接口来完成的,面向接口编程使得我们可以不关注类本身的状态,只需要关注他们的共有特点(接口方法)即可。将本身需要对类的持有,降低到了对接口的持有。解耦性强。所以我们应当面向接口编程,来获取更高的自由度