观察者模式定义了一种一对多的依赖关系,让多个观察者监听一个主题对象,当这个主题对象发生变化的时候,会通知所有观察者对象进行更新。
观察者模式的好处是:它解除了观察者和目标之间的耦合关系。目标不需要知道它的观察者的任何信息。相反,目标只是允许观察这订阅事件。当目标产生一个事件的时候,他简单地把事件传递给每一个观察者。
在观察者模式中,存在四个角色:
抽象主题角色
主题角色可以拥有一个观察者对象的列表,同时提供一个接口可以添加和移除观察者,主题角色又为被观察(Observable)角色,可以用一个抽象类或者一个接口实现;在具体的情况下也不排除使用具体类实现。抽象观察者角色
为所有具体观察者定义接口,在得到通知的时候更新自己
具体主题
抽象主题角色的子类,通常持有一个方法,可以更新通知所有的观察者
具体观察着
具体观察者为抽象观察者的子类,具体观察者角色实现抽象观察者角色所要求的更新自己的接口,以便使本身的状态与主题的状态自恰。
Observer 机制的实现
1、Subject 主题 需要为注册和注销观察者提供一个接口
2、Observer 观察者 需要提供一个从Subject 接口通知的接口
下图说面几种角色之间的关系:
其实说明了这么多理论性的东西,可以还不足以理解,看起来挺抽象的,我下面就用代码来展示一下把:
首先我们需要一个抽象主题角色
public interface Subject{
/** 注册观察者 */
public void addObserver(Observer observer);
/** 注销观察者 */
public void removeObserver(Observer observer);
}
下面我们需要一个抽象观察者对象
public interface Observer{
/** 当被观察者状态改变的时候,观察者更新状态的接口 */
public void update(String msg);
}
下面我开始写具体主题对象 :
public class ReadSubject implements Subject{
/** 这个一个集合,管理所有的观察者 */
private List<Observer> list = new ArrayList<Observer>();
/** 注册观察者 */
@Override
public void addObserver(Observer observer){
list.add(observer);
}
/** 移除观察者 */
@Override
public void removeObserver(Observer observer){
list.remove(observer);
}
/** 通知所有观察者状态更新了 */
public void notifyAllObserver(String msg){
for(Observer ob : list){
ob.update(msg);
}
}
}
好啦,,上面就是具体主题对象,也就是被观察的对象,当状态改变的时候我们需要调用一下 notifyAllObserver();
方法通知所有观察者,然后所有的观察这就会调用update 方法,看到这里是不是觉得缺少点什么呢?对就是具体观察者对象。
我们的具体观察这对象只需要实现了Observer 接口就可以了
public Observer1 implements Observer{
public void update(String msg){
System.out.println("观察者1被通知了消息:"+msg);
}
}
public Observer2 implements Observer{
public void update(String msg){
System.out.println("观察者2被通知了消息:"+msg);
}
}
最后我们写一个类来走一下流程:
public class Main {
public static void main(String[] args) {
RealSubject realSub = new RealSubject();
Observer1 o1 = new Observer1();
Observer2 o2 = new Observer2();
realSub.addObserver(o1);
realSub.addObserver(o2);
realSub.notifyAllObserver("状态改变了");
}
}
运行结果是:
好啦,观察者模式就是这些内容了,其实就编码方面来说,就是利用了接口,一个对象持有多个观察者(对象,接口的实例),然后当需要通知的时候就调用接口(对象)的方法通知,然后所有的对象就收到了消息。
观察者模式的效果:
观察着模式有一下一些优点:
- 观察者与被观察者之间建立一个抽象的耦合。被观察者只知道一个具体观察者列表,每一个具体观察者都有一个接受消息的接口。所以,被观察者并不知道任何一个具体观察者。
- 第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知。
观察者模式的缺点 :
第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。
第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的,仅仅知道发生了什么变化而已。