适用场合:当一个对象的改变需要同时改变(且它不知道多少个其它对象需要改变)其它对象时,我们就可以使用观察者模式,其实它所做的工作就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体的细节或者详细信息,从而使得各自的变化不会影响到另一边的变化。
那么什么是观察者模式呢?
观察者模式又叫发布-订阅模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题,当这个主题发生变化时,会通知所有观察者对象,让它们能够更新自己。下面给出观察者模式的组装代码部分,再一步步来说明如何实现观察模式:
package com.ops.observer.main;
import org.junit.Test;
import com.ops.observer.base.Boss;
import com.ops.observer.base.NBAObserver;
import com.ops.observer.base.StockObserver;
public class ObserverClient {
@Test
public void test() {
Boss huhansan = new Boss();
NBAObserver tongshi1 = new NBAObserver("张三", huhansan);
StockObserver tongshi2 = new StockObserver("李四", huhansan);
huhansan.setAction("我胡汉三来了!");
huhansan.attach(tongshi1);
huhansan.attach(tongshi2);
huhansan.notifyEvent();
}
}
上面的Boss其实是实现了某一个主题Subject,而NBAObserver与StockObserver则是具体的观察者,它会去监听某一主题,这里是监听Boss这个Subject,当Boss调用setAction设置一个动作表示自己发生变化时,它会去通知所有的观察者,而通过attach订阅了这个主题的观察者就可以收到相应的通知。
下面来看看Boss的实现,它其实是一个Subject主题的具体实现:
1 Subject.java
package com.ops.observer;
import java.util.ArrayList;
import java.util.List;
public abstract class Subject {
protected List<Observer> observers = new ArrayList<Observer>();
private String action = null;
abstract public void notifyEvent();
abstract public void attach(Observer observer);
abstract public void detach(Observer observer);
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
}
2 Boss.java
package com.ops.observer.base;
import com.ops.observer.Observer;
import com.ops.observer.Subject;
public class Boss extends Subject {
@Override
public void notifyEvent() {
for (Observer obserer : observers) {
obserer.update();
}
}
@Override
public void attach(Observer observer) {
this.observers.add(observer);
}
@Override
public void detach(Observer observer) {
this.observers.remove(observer);
}
}
上面是主题的实现,现在来看看观察者的实现,NBAObserver与StockObserver是具体的观察者,它们都实现了抽象类Observer(当某一主题改变时,它需要通知的观察者变不是具体的观察者,而一个抽象的观察者,也就是这里的Observer,这样就可以实现解耦合,这就是依赖-倒转原则最佳体现,不依赖于具体的细节而依赖于抽象,这样比较便于扩展):
1 Observer.java
package com.ops.observer;
public abstract class Observer {
protected String name = null;
protected Subject subject = null;
public Observer(String name, Subject subject) {
this.name = name;
this.subject = subject;
}
abstract public void update();
}
2 NBAObserver
package com.ops.observer.base;
import com.ops.observer.Observer;
import com.ops.observer.Subject;
public class NBAObserver extends Observer {
private String TAG = "NBAObserver";
public NBAObserver(String name, Subject subject) {
super(name, subject);
}
@Override
public void update() {
System.out.println(TAG + ": " + subject.getAction() + "," + name +
" 老板回来了,请关闭NBA直播,继续工作!");
}
}
3 StockObserver
package com.ops.observer.base;
import com.ops.observer.Observer;
import com.ops.observer.Subject;
public class StockObserver extends Observer {
private String TAG = "StockObserver";
public StockObserver(String name, Subject subject) {
super(name, subject);
}
@Override
public void update() {
System.out.println(TAG + ": " + subject.getAction() + "," + name +
" 老板回来了,请关闭股票行情,继续工作!");
}
}