针对问题:在消息-通知 的程序结构中,为了通知待通知的对象,需在消息服务中持有所有的待通知的对象,消息服务和大量的待通知对象紧密的耦合在一起,无论是新添加一个通知对象、或是取消通知都必须改变消息服务。为了解决这个问题,消息服务(主题)必须提供注册和删除的接口,不仅如此,主题要想统一管理待通知的对象(观察者),所有观察者必须遵循某一规范,也就是在所有观察者中抽象出一个接口,主题无须打理观察者是什么,只要它遵循规范就行,这样就将以前的耦合进行了抽象,也就是松耦合。
观察者模式结构图:
观察者模式实现代码:
/** * 主题接口 * @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 * */ } }