Java中的观察者模式

让一个类能够被观察,则该类需要继承java.util.Observable类。

要让一个类成为观察者,则该类需要实现java.util.Observable接口。

让观察者和被观察者建立联系通过Observable的addObserver(Object obj)方法。

让被观察者通知观察者,通过Observable类中的setChanged()和notifyObservers(Object obj)方法。

下面的例子定义了一个售房中心类和一个卖家类。售房中心为被观察者,买房者为观察者。售房中心房价发生变化,则将相应的信息通知买房者。

代码如下:

import java.util.*;


class HouseSellCenter extends Observable
{
    public String name;
    public float price;
    public HouseSellCenter(String name, float price)
    {
        this.name = name;
        this.price = price;
    }

    public void changePrice(float price)
    {
        this.price = price;
        super.setChanged();
        super.notifyObservers(price);
    }

    public String toString()
    {
        return "name:" + this.name + " price:"  +this.price; 
    }
}


class Buyer implements Observer
{
    public String name;
    public Buyer(String name)
    {
        this.name = name;
    }


    public void update(Observable o, Object arg)
    {
        HouseSellCenter hsc = (HouseSellCenter)o;
        System.out.println(this.name+"观察到:"+hsc.name+"房价变为:" + arg + "万");
    }
}

class Hello
{
    public static void main(String[] args) 
    {
         HouseSellCenter hsc = new HouseSellCenter("金悦城",1.3f);
         Buyer buyer1 = new Buyer("金旭地产");
         Buyer buyer2 = new Buyer("龙城中介");
         Buyer buyer3 = new Buyer("祥龙置业");
         hsc.addObserver(buyer1);
         hsc.addObserver(buyer2);
         hsc.addObserver(buyer3);

         System.out.println("============");
         hsc.changePrice(1.5f);
         System.out.println("============");

         sleep(3000);
        
         System.out.println("============");
         hsc.changePrice(1.2f);
         System.out.println("============");
    }

    public static void sleep(int timeSpan)
    {
        try
        {
            Thread.sleep(timeSpan);
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }
}

输出结果:

============
祥龙置业观察到:金悦城房价变为:1.5万
龙城中介观察到:金悦城房价变为:1.5万
金旭地产观察到:金悦城房价变为:1.5万
============
============
祥龙置业观察到:金悦城房价变为:1.2万
龙城中介观察到:金悦城房价变为:1.2万
金旭地产观察到:金悦城房价变为:1.2万
============

上面的代码是利用了Java对观察者模式的支持。下面用另一个例子说明观察者模式运行规则。

Observerable接口(定义被观察者的规范):

public interface Observerable 
{
    void addObserver(ObserverBehavior newObserver);
    void removeObserver(ObserverBehavior observerToBeRemoved);
    void notifyAllObservers();
}

ObserverBehavior接口(定义观察者的规范):

public interface ObserverBehavior 
{
    void update(float temperature, float humidity, float pressure);
}

WeatherData类实现Observerable接口,其是真实的被观察者类:

import java.util.List;
import java.util.ArrayList;

public class WeatherData implements Observerable 
{
    private List<ObserverBehavior> observerList;
    private float temperature;
    private float humidity;
    private float pressure;
    
    public WeatherData()
    {
         this.observerList = new ArrayList<ObserverBehavior>();
    }
    
    @Override
    public void addObserver(ObserverBehavior newObserver) 
    {
        // TODO Auto-generated method stub
        this.observerList.add(newObserver);
    }

    @Override
    public void notifyAllObservers() 
    {
        // TODO Auto-generated method stub
        for(ObserverBehavior observer : this.observerList)
        {
            observer.update(this.temperature, this.humidity, this.pressure);
        }
    }

    @Override
    public void removeObserver(ObserverBehavior observerToBeRemoved) 
    {
        // TODO Auto-generated method stub
        this.observerList.remove(observerToBeRemoved);
    }
    
    
    public void weatherChanged(float temperature, float humidity, float pressure)
    {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        
        this.notifyAllObservers();
    }
}

MobileDevices实现ObserverBehavior类(真正的观察者):

public class MobileDevices implements ObserverBehavior 
{
    private String name;
    public MobileDevices(String name)
    {
        this.name = name;
    }
    @Override
    public void update(float temperature, float humidity, float pressure) 
    {
        // TODO Auto-generated method stub
        System.out.println(this.name + "观察到当前 --> 温度:" + temperature + " 湿度:" + humidity + " 气压:" + pressure);
    }
    
    @Override
    public boolean equals(Object obj)
    {
        if(this == obj)
            return true;
        
        if(!(obj instanceof MobileDevices))
            return false;
        
        MobileDevices otherOne = (MobileDevices)obj;
        if(this.name.equals(otherOne.name))
            return true;
        else
            return false;
    }

}

WhiteBoard实现了ObserverBehavior类(另一个真正的观察者):

public class WhiteBoard implements ObserverBehavior 
{
    private String name;
    public WhiteBoard(String name)
    {
        this.name = name;
    }
    
    
    @Override
    public void update(float temperature, float humidity, float pressure) 
    {
        // TODO Auto-generated method stub
        System.out.println(this.name + "观察到当前 --> 温度:" + temperature + " 湿度:" + humidity + " 气压:" + pressure);
    }

}

主方法测试:

public class Tester 
{

    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        // TODO Auto-generated method stub
        WeatherData subject = new WeatherData();
        WhiteBoard wb = new WhiteBoard("中央广场白板");
        MobileDevices iphone = new MobileDevices("iphone手机");
        MobileDevices android = new MobileDevices("安卓手机");
        subject.addObserver(wb);
        subject.addObserver(iphone);
        
        subject.weatherChanged(12, 23, 33);
        subject.removeObserver(new MobileDevices("iphone手机"));
        subject.addObserver(android);
        
        subject.weatherChanged(22, 43, 25);
    }
}

输出结果:

中央广场白板观察到当前 --> 温度:12.0 湿度:23.0 气压:33.0

iphone手机观察到当前 --> 温度:12.0 湿度:23.0 气压:33.0

中央广场白板观察到当前 --> 温度:22.0 湿度:43.0 气压:25.0

安卓手机观察到当前 --> 温度:22.0 湿度:43.0 气压:25.0

总结:

被观察者应该具备以下功能:

  1) 能增加一个观察者 addObserver

  2)能移除一个观察者 removeObserver

  3)在数据改变的时候能将相应的信息通知给被观察者 notifyAllObservers

观察者应具备以下功能:

  1) update方法用于观察者接收被观察者的推送信息