# 观察者模式
## 概念:一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。(--维基百科)
## 类图
### 类和接口解释:
#### Subject:被观察的对象,需要维护一个观察者对象的列表(List)。其中还有三个方法:
##### 1.notifyObserves():通知观察者,其实就是依次调用观察者对象的notify方法。
##### 2.addObserver():增加观察者,将观察者添加到维护的列表中。
##### 3.deleteObserver():删除观察者,从列表中将观察者remove掉。
#### Observer:观察者对象,里面包含一个notify方法,在被观察者的状态被改变时,此方法被调用。
#### ConcreteSubjectA/B:具体的被观察者对象,定义业务处理逻辑。
#### ConcreteObserverA/B:具体的观察者,当被观察者改变时所需要处理的业务逻辑。
## 代码实现
### 1.定义被观察者
package com.mgl.study.observer;
import java.util.Vector;
/**
* Desciption:被观察者的主题角色
*/
public abstract class Subject {
private Vector<Observer> observers = new Vector<Observer>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void deleteObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObserves() {
for (Observer observer : observers) {
observer.update();
}
}
// bussiness method
public abstract void doSomething();
}
### 定义具体的被观察者
package com.mgl.study.observer;
/**
* 具体的被观察者对象
*/
public class ConcreteSubject extends Subject {
public void doSomething() {
System.out.println("被观察者事件发生...");
this.notifyObserves();
}
}
### 定义观察者
package com.mgl.study.observer;
/**
* Desciption:观察者对象
*/
public interface Observer {
// 图中叫notify
void update();
}
### 定义两个具体的观察者
package com.mgl.study.observer;
/**
* Desciption:具体的观察者对象A
*/
public class ConcreteObserverA implements Observer {
public void update() {
System.out.println("观察者对象A收到通知,方法被调用!");
}
}
package com.mgl.study.observer;
/**
* Desciption:具体的观察者对象B
*/
public class ConcreteObserverB implements Observer {
public void update() {
System.out.println("观察者对象B收到通知,方法被调用!");
}
}
### 测试结果
package com.mgl.study.observer;
public class ObserverTest {
public static void main(String[] args) {
Observer observerA = new ConcreteObserverA();
Observer observerB = new ConcreteObserverB();
Subject subject = new ConcreteSubject();
subject.addObserver(observerA);
subject.addObserver(observerB);
subject.doSomething();
// 输出结果
/**
* 被观察者事件发生...
* 观察者对象A收到通知,方法被调用!
* 观察者对象B收到通知,方法被调用!
*/
subject.deleteObserver(observerA);
subject.doSomething();
// 输出结果
/**
* 被观察者事件发生...
* 观察者对象B收到通知,方法被调用!
*/
}
}
## 总结
### 优点:观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,那么这个对象必然跨越抽象化和具体化层次。
### 缺点:
#### 1.如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
#### 2.如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。
#### 3.如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
#### 4.虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。(不可逆)