针对问题:在消息-通知 的程序结构中,为了通知待通知的对象,需在消息服务中持有所有的待通知的对象,消息服务和大量的待通知对象紧密的耦合在一起,无论是新添加一个通知对象、或是取消通知都必须改变消息服务。为了解决这个问题,消息服务(主题)必须提供注册和删除的接口,不仅如此,主题要想统一管理待通知的对象(观察者),所有观察者必须遵循某一规范,也就是在所有观察者中抽象出一个接口,主题无须打理观察者是什么,只要它遵循规范就行,这样就将以前的耦合进行了抽象,也就是松耦合。
观察者模式结构图:
观察者模式实现代码:
/**
* 主题接口
* @author bruce
*
*/
public interface Subject {
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
}
/**
* 观察者接口
* @author bruce
*
*/
public interface Observer {
public void update();
}
/**
* 主题实现
* @author bruce
*
*/
public class ConcreteSubject implements Subject{
private List<Observer> observers=new ArrayList<Observer>();
public void notifyObservers() {
for(Observer observer:observers){
observer.update();
}
}
public void registerObserver(Observer observer) {
if(!observers.contains(observer)){
observers.add(observer);
}
}
public void removeObserver(Observer observer) {
if(observers.contains(observer)){
observers.remove(observer);
}
}
}
/**
* 观察者A
* @author bruce
*
*/
public class ConcreteObserverA implements Observer{
private Subject subject;
public ConcreteObserverA(Subject subject){
this.subject=subject;
this.subject.registerObserver(this);
}
public void update() {
// TODO Auto-generated method stub
System.out.println("通知观察者A");
}
}
/**
* 观察者B
* @author bruce
*
*/
public class ConcreteObserverB implements Observer{
private Subject subject;
public ConcreteObserverB(Subject subject){
this.subject=subject;
this.subject.registerObserver(this);
}
public void update() {
// TODO Auto-generated method stub
System.out.println("通知观察者B");
}
}
/**
* 测试
* @author bruce
*
*/
public class Client {
public static void main(String[] args) {
Subject subject=new ConcreteSubject();//创建主题
Observer observerA=new ConcreteObserverA(subject);//创建观察者A,并注册
Observer observerB=new ConcreteObserverB(subject);//创建观察者B,并注册
System.out.println("---------");
subject.notifyObservers();
System.out.println("---------");
subject.removeObserver(observerA);//观察者A取消收听
subject.notifyObservers();
/**
* output:
* ---------
通知观察者A
通知观察者B
---------
通知观察者B
*
*/
}
}