设计模式(十九)----- 观察者模式(Observer)----(JAVA版)

    观察者模式是一个比较常用也是一个比较智能的设计模式,它主要作用是当一个对象(被观察者)改变时,所有依赖此对象的对象(观察者)都会相应的改变。比如,我们在手机上设置字体后,所有的对象的字体也相应的改变;Android系统中,ContentObserver,Intent就是非常典型的观察者模式。它的地位应该是非常重要的,引用Nicholas Lesiecki()的话说,它是“设计模式中的皇后”。


观察者模式(Observer):

    简单地说,观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监察一个主题对象。这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象,使这些观察者对象能够自动更新。


适用性:

(1)当一个抽象模型有两个方面,其中一个方面依赖另一方面

     将这二者封装到独立的对象中以使它们可以独立的改变和复用

(2)当对一个对象的改变需要同时改变其它对象,而不知道具体有多少个对角有待改变

(3)当一个对象必须通知其它对象,而它又不能假定其它对象是谁


参与者:

(1)Subject(目标)

    目标知道它的观察者,可以有任意多个观察者观察同一个目标,提供注册和删除观察者对象的接口

(2)Observer(观察者)

    为所有的具体观察者定义一个接口,在得到通知时更新自己

(3)ConcreteSubject(具体目标)

    保存对具体观察者对象有用的内部状态;在这种内部状态改变时给其观察者发出一个通知;具体目标又叫作具体被观察者角色;

(4)ConcreteObserver(具体观察者)

      保存一个指向ConcreteSubject对象的引用;和一个与目标的状态相符的状态。具体观察者角色实现抽象观察者角色所要求的更新自己的接口,以便使本身的状态与目标的状态自一致。


观察者模式的静态结构:



第一个例子:

Subject:

public abstract class Citizen {
   List pols;
   String help = "normal";
   public void setHelp(String help){
      this.help = help;
   }
   public String getHelp(){
      return this.help;
   }
   abstract void sendMessage(String help);
   public void setPolicemen(){
      this.pols = new ArrayList();
   }
   public void register(Policeman pol){
      this.pols.add(pol);
   }
   public void unRegister(Policeman pol){
       this.pols.remove(pol);
   }
}

Observer:

public interface Policeman{
   void action(Citizen ci);
}

ConcreteSubject:

public class HuangPuCitizen extends Citizen {
   public HuangPuCitizen(Policeman pol){
      setPolicemen();
      register(pol);
   }

   public void sendMessage(String help){
      setHelp(help);
      for(int i = 0;i<pols.size();i++){
          Policeman pol = pols.get(i);
          //通知警察行动
          pol.action(this);
      }
    }
}
public class TianHeCitizen extends Citizen {
   public TianHeCitizen(Policeman pol){
      setPolicemen();
      register(pol);
   }

   public void sendMessage(String help){
      setHelp(help);
      for(int i = 0;i<pols.size();i++){
          Policeman pol = pols.get(i);
          //通知警察行动
          pol.action(this);
      }
    }
}
ConcreteObserver:

ConcreteObserver:public class HuangPuPoliceman implements Policeman {
   public void action(Citizen ci){
      String help = ci.getHelp();
      if(help.equals("normal")) {
         System.out.println("正常,不用出去");
       }

      if(help.equals("unnormal")) {
         System.out.println("有犯罪行为,黄埔警察出去");
       }
 }}
public class TianHePoliceman implements Policeman {
   public void action(Citizen ci){
      String help = ci.getHelp();
      if(help.equals("normal")) {
         System.out.println("正常,不用出去");
       }
      if(help.equals("unnormal")) {
         System.out.println("有犯罪行为,天河警察出去");
       }
   }
}

Test:

public class Test{
   public static void main(String[] args) {
      Policeman thPol = new TianHePoliceman();
      Policeman hpPol = new HuangPuPoliceman();
      Citizen citizen = new HuangPuCitizen(hpPol);
      citizen.sendMessage("unnormal");
      citizen.sendMessage("normal");
      System.out.println("======================");    
      Citizen citizen = new TianHeCitizen(thPol);
      citizen.sendMessage("normal");
      citizen.sendMessage("unnormal");
 }}


result:有犯罪行为,黄埔警察出去
正常,不用出去
======================
正常,不用出去
有犯罪行为,天河警察出去


第二个例子:Java语言提供的对观察者模式的支持

     在Java语言的java.util库里面,提供了一个Observable类以及一个Observer接口,构成Java语言对观察者模式的支持。

    Observer接口

     这个接口只定义了一个方法,update()。当被观察者对象的状态发生变化时,这个方法就会被调用。这个方法的实现应当调用每一个被观察者对象的notifyObservers()方法,从而通知所有的观察对象。


java.util.Observer接口的源代码:

package java.util;

public interface Observer
{
/**
* 当被观察的对象发生变化时,这个方法会被调用。
*/
void update(Observable o, Object arg);
}

Observable类

       被观察者类都是java.util.Observable类的子类。java.util.Observable提供公开的方法支持观察者对象,这些方法中有两个对Observable的子类非常重要:一个是setChanged(),另一个是notifyObservers()。第一个方法setChanged()被调用之后会设置一个内部标记变量,代表被观察者对象的状态发生了变化。第二个是notifyObservers(),这个方法被调用时,会调用所有登记过的观察者对象的update()方法,使这些观察者对象可以更新自己。

     java.util.Observable类还有其它的一些重要的方法。比如,观察者对象可以调用java.util.Observable类的addObserver()方法,将对象一个一个加入到一个列表上。当有变化时,这个列表可以告诉notifyObservers()方法那些观察者对象需要通知。由于这个列表是私有的,因此java.util.Observable的子对象并不知道观察者对象一直在观察着它们。


被观察者类Observable的源代码:

package java.util;
public class Observable
{
  private boolean changed = false;
  private Vector obs;

/** 用0个观察者构造一个被观察者。**/

public Observable()
{
  obs = new Vector();
}

/**
* 将一个观察者加到观察者列表上面。
*/
public synchronized void addObserver(Observer o)
{
  if (!obs.contains(o))
  {
    obs.addElement(o);
  }
}

/**
* 将一个观察者对象从观察者列表上删除。
*/
public synchronized void deleteObserver(Observer o)
{
  obs.removeElement(o);
}

/**
* 相当于 notifyObservers(null)
*/
public void notifyObservers()
{
   notifyObservers(null);
}

/**
* 如果本对象有变化(那时hasChanged 方法会返回true)
* 调用本方法通知所有登记在案的观察者,即调用它们的update()方法,
* 传入this和arg作为参量。
*/
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();
}

/**
* 将“已变化”设为true
*/
protected synchronized void setChanged()
{
   changed = true;
}

/**
* 将“已变化”重置为false
*/
protected synchronized void clearChanged()
{
   changed = false;
}

/**
* 探测本对象是否已变化
*/
public synchronized boolean hasChanged()
{
   return changed;
}

/**
* 返还被观察对象(即此对象)的观察者总数。
*/
public synchronized int countObservers()
{
   return obs.size();
}
}

     这个Observable类代表一个被观察者对象。一个被观察者对象可以有数个观察者对象,一个观察者可以是一个实现Observer接口的对象。在被观察者对象发生变化时,它会调用Observable的notifyObservers方法,此方法调用所有的具体观察者的update()方法,从而使所有的观察者都被通知更新自己。见下面的类图:




    为了说明怎样使用Java所提供的对观察者模式的支持,本节给出一个非常简单的例子。在这个例子里,被观察对象叫做Watched,也就是被监视者;而观察者对象叫做Watcher。Watched对象继承自java.util.Obsevable类;而Watcher对象实现了java.util.Observer接口。另外有一个对象Tester,扮演客户端的角色。

Watcher类的源代码

package com.javapatterns.observer.watching;

import java.util.Observable;
import java.util.Observer;

public class Watcher implements Observer
{
public Watcher(Watched w)
{
   w.addObserver(this);
}

public void update( Observable ob, Object arg)
{
   System.out.println("Data has been changed to: '" + ((Watched)ob).retrieveData() + "'");
}
}

Watched类的源代码

package com.javapatterns.observer.watching;

import java.util.Observable;

public class Watched extends Observable
{
private String data = "";

public String retrieveData()
{
   return data;
}

public void changeData(String data)
{
  if ( !this.data.equals( data) )
  {
    this.data = data;
    setChanged();
  }

notifyObservers();
}
}

Tester类的源代码

package com.javapatterns.observer.watching;

import java.util.Observer;

public class Tester
{
static private Watched watched;
static private Observer watcher;

public static void main(String[] args)
{
   watched = new Watched();

   watcher = new Watcher(watched);

  watched.changeData("In C, we create bugs.");
  watched.changeData("In Java, we inherit bugs.");
  watched.changeData("In Java, we inherit bugs.");
  watched.changeData("In Visual Basic, we visualize bugs."); 
}
}

可以看出,虽然客户端将Watched对象的内部状态赋值了四次,但是值的改变只有三次:

watched.changeData("In C, we create bugs.");
watched.changeData("In Java, we inherit bugs.");
watched.changeData("In Java, we inherit bugs.");
watched.changeData("In Visual Basic, we visualize bugs.");

  对应地,Watcher对象汇报了三次改变,下面就是运行时间程序打印出的信息:

Data has been changed to: 'In C, we create bugs.'

Data has been changed to: 'In Java, we inherit bugs.'

Data has been changed to: 'In Visual Basic, we visualize bugs.'


参考资料:

http://www.blogjava.net/supercrsky/articles/202544.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值