观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并更新。
主题和观察者定义了一对多的关系,观察者依赖于主题。当主题对象的状态发生改变时,观察者就会被通知。根据通知观察者进行相关操作。
一、 涉及角色:主题接口,观察者接口,具体主题,具体观察者。
优点:主题是真正拥有数据的对象,观察者是主题的依赖者,在数据变化跟新时这样比多个对象控制同一份数据,可以更干净的OO设计。
缺点:并不是所有的观察者都需要这份数据,有可能只需要其中的一部分,却接收了一堆数据。(JDK中的观察这模式,提供了支持,支持以个getter方法的主动获取数据)
二、代码实例
(1)抽象观察者角色
1 public interface Observer { 2 /** 3 * <p>观察者对象更新自己的信息</p> 4 * @author maxianming 2016-1-11 下午2:11:44 5 * @param Message 6 */ 7 public void update(String Message); 8 }
(2)抽象主题角色
1 public interface Subject { 2 /** 3 * <p>主题对象中注册一个观察者</p> 4 * @author maxianming 2016-1-11 下午2:09:17 5 * @param observer 6 */ 7 public void registerObserver(Observer observer); 8 /** 9 * <p>主题对象中删除一个观察者</p> 10 * @author maxianming 2016-1-11 下午2:09:53 11 * @param observer 12 */ 13 public void removeObserver(Observer observer); 14 /** 15 * <p>主题对象改变通知所有的观察者对象</p> 16 * @author maxianming 2016-1-11 下午2:11:05 17 */ 18 public void notifyObservers(); 19 }
(3)具体观察者角色
1 public class ConcreteObserver implements Observer { 2 private Subject subject; 3 4 public ConcreteObserver(Subject subject){ 5 this.subject = subject; 6 subject.registerObserver(this); 7 } 8 9 @Override 10 public void update(String message) { 11 System.out.println("具体观察者得到 【主题对象的信息】为:" + message); 12 } 13 14 }
(4)具体主题角色
1 public class ConcreteSubject implements Subject { 2 private ArrayList<Observer> observers; 3 private String message; 4 5 public ConcreteSubject(){ 6 this.observers = new ArrayList<Observer>(); 7 } 8 @Override 9 public void registerObserver(Observer observer) { 10 this.observers.add(observer); 11 } 12 13 @Override 14 public void removeObserver(Observer observer) { 15 boolean hasObserver = this.observers.contains(observer); 16 if(hasObserver){ 17 this.observers.remove(observer); 18 } 19 } 20 21 @Override 22 public void notifyObservers() { 23 for (int i = 0; i < observers.size(); i++) { 24 Observer observer = observers.get(i); 25 if(observer != null){ 26 observer.update(this.message); 27 } 28 29 } 30 } 31 32 public void setData(String message){ 33 this.message = message; 34 //状态改变,通知观察者 35 this.notifyObservers(); 36 } 37 }
(5)客户端
1 public class Client { 2 public static void main(String[] args) { 3 //1、主题对象 4 ConcreteSubject subject = new ConcreteSubject(); 5 //2、观察者对象 6 Observer observer = new ConcreteObserver(subject); 7 //3、主题对象信息改变 8 subject.setData("213123213"); 9 10 //4、删除观察者对象 11 subject.removeObserver(observer); 12 //5、主题对象信息gaibian 13 subject.setData("3456178"); 14 } 15 }
三、JDK中观察者模式
JDK对观察者模式提供了支持。主题类Observable,具体主题类可以继承JDK中实现类Observable类。具体观察者可以实现JDK中的观察者接口Observer接口。
主题通知观察者:继承JDKObservable的主题接口,通知观察者对象步骤。
(1)先调用Observable中的setChanged()方法。标记状态已经改变
(2)再调用notifyObservers()或notifyObservers(arg)(带参数方法可以推送指定的参数)。