观察者模式

来源:互联网 发布:ios 提取网页数据 编辑:程序博客网 时间:2024/06/06 23:16

1 定义

    观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够采取相应的行为。

   观察者模式被称为是模式中的皇后,是一种常用的触发机制,而且JDK也对它做了实现,可见该设计模式的重 要位置。在图形化设计的软件中,为了实现视图和事件处理的分离,大多都采用了 Observer模式,比如java的Swing框架。在现实的应用系统中也有好多 应用,比如像当当网、京东商城一类的电子商务网站,如果你对某件商品比较关注,可以 放到收藏架,那么当该商品降价时,系统给您发送手机短信或邮件。这就是观察者模式的 一个典型应用,商品是被观察者;关注该商品的客户就是观察者。

2 为什么使用观察者模式

    在软件系统中,当一个或者多个对象的行为依赖于另一个对象的状态时,观察者模式就非常有用。如果不使用观察者模式提供的通用结构,而需要实现类似的功能时,则只能在另一个线程中不停地监听对象所依赖的状态,即安排一个轮询。在一个复杂的系统中,可能会因此开启很多线程来实现这一功能,这将使系统的性能产生额外的负担。观察者模式的意义也就在此,它可以在单线程中,使某一对象及时得知自身所依赖对象的状态的变化。
    观察者模式可用于时间监听、通知发布等场合。可以确保观察者在不使用轮询监控的情况下,及时收到相关消息和事件。

3 观察者模式的类图和四个角色


3.1 主题接口

    指被观察的对象。当其状态发生改变或者某一事件发生时,它会将这个变化通知观察者。它维护了观察者所需要依赖的状态。

3.2 具体主题

    具体主题实现了主题接口中的方法。比如,新增观察者,删除观察者,通知观察者,更改主题状态等。其内部维护一个观察者列表,每个主题都可以有任何数量的观察者。在具体主题内部状态改变时,给所有登记过的观察者发出通知。

3.3 观察者接口

    观察者接口定义了观察者的基本方法。当依赖状态发生改变时,主题接口就会调用观察者的update()方法。

3.4 具体观察者

    实现了观察者接口的update()方法,具体处理当主题状态发生改变时,所应该采取的业务逻辑。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用,即将主题对象的引用作为update()方法的参数。

4 代码实现

主题接口:
<pre name="code" class="java">package study.observer;public interface ISubject {void attach(IObserver observer);void detach(IObserver observer);void notifyObservers();void changeState(String state);}
具体主题:
import java.util.Vector;public class Subject implements ISubject {private Vector<IObserver> observers=new Vector<IObserver>();private String state;public void changeState(String state) {this.state=state;notifyObservers();}@Overridepublic void attach(IObserver observer) {// TODO Auto-generated method stubobservers.add(observer);}@Overridepublic void detach(IObserver observer) {// TODO Auto-generated method stubobservers.remove(observer);}@Overridepublic void notifyObservers() {// TODO Auto-generated method stubfor (IObserver observer : observers) {observer.update(this);}}public String getState() {return state;}}
观察者接口:
public interface IObserver {void update(ISubject subject);}
具体观察者:(可以定义多个具体观察者)
public class ConcreteObserver implements IObserver {@Overridepublic void update(ISubject subject) {// TODO Auto-generated method stubSystem.out.println("收到了主体对象状态变化的通知,当前主题对象的状态是:"+((Subject)subject).getState());System.out.println("这里可以根据主体对象的状态,设置相应的业务逻辑,不同的观察者有不同的业务逻辑,同一观察者,面对不同的"+ "主题状态,也有不同的业务逻辑");}}
测试代码:(可以对同一个主题对象,添加多个观察者)
public class TestObserver {public static void main(String[] args) {ISubject subject=new Subject();IObserver observer=new ConcreteObserver();subject.attach(observer);subject.changeState("新状态");}}

5 JDK的对观察者模式的支持

    在JDK中已经实现了一套观察者模式。下面看一下是如何实现的:

5.1 主题类,被观察者

java.util.Observable:
import java.util.Observer;import java.util.Vector;public class Observable {  private boolean changed = false;  private Vector obs;  /**   * 持有的观察者列表,注意,这个列表是需要同步的。   * 因此,用Vector,而没有用ArrayList   */  public Observable() {    obs = new Vector();  }  /**   * 添加观察者到主题对象的观察者列表中去   */  public synchronized void addObserver(Observer o) {    if (o == null)      throw new NullPointerException();    if (!obs.contains(o)) {      obs.addElement(o);    }  }  /**   * 删除一个观察者   */   public synchronized void deleteObserver(Observer o) {    obs.removeElement(o);  }  public void notifyObservers() {    notifyObservers(null);  }  /**   * 通知操作,即被观察者发生变化,通知对应的观察者进行事先设定的操作   */   public void notifyObservers(Object arg) {    Object[] arrLocal;    synchronized (this) {      if (!changed)        return;      arrLocal = obs.toArray();      clearChanged();    }    for (int i = arrLocal.length-1; i>=0; i--)      ((Observer)arrLocal[i]).update(this, arg);  }  public synchronized void deleteObservers() {    obs.removeAllElements();  }  protected synchronized void setChanged() {    changed = true;  }  protected synchronized void clearChanged() {    changed = false;  }  public synchronized boolean hasChanged() {     return changed;  }  public synchronized int countObservers() {    return obs.size();  }}

5.2 观察者接口

java.util.Observer:
package java.util;public interface Observer {    /**     * @param   o     the observable object.     * @param   arg   an argument passed to the <code>notifyObservers</code>     *                 method.     */    void update(Observable o, Object arg);}

5.3 使用JDK的观察者模式

    下面简单模拟用户在京东上网购的场景,被观察者是顾客,观察者是京东,顾客维护的观察者列表中有京东(也可以额外添加其他的,比如税务部门等),当顾客已付款,则会通知京东,京东收到付款通知就会配送发货。
主题对象,继承Observable类:
package study.observer;import java.util.Observable;public class Customer extends Observable {private String state="";public void changeState(String state) {if (!this.state.equals(state)) {setChanged();setState(state);}notifyObservers(state);clearChanged();}public String getState() {return state;}public void setState(String state) {this.state = state;}}
观察者,实现Observer接口:
package study.observer;import java.util.Observable;import java.util.Observer;public class JingDong implements Observer {@Overridepublic void update(Observable o, Object arg) {// TODO Auto-generated method stubif (((Customer)o).getState().equals("已付款")) {System.out.println("收到付款通知,开始配送发货");}}}
测试代码:
package study.observer;import java.util.Observable;import java.util.Observer;public class TestObserver {public static void main(String[] args) {Observable customer=new Customer();Observer jd=new JingDong();customer.addObserver(jd);((Customer)customer).changeState("已付款");}}
运行结果:
收到付款通知,开始配送发货

6 参考文章

<1>Java程序性能优化. 葛一鸣等著
<2>http://www.cnblogs.com/machine/p/3262378.html

<3>http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html

0 0
原创粉丝点击