美文网首页
观察者模式(Observer)(常用)

观察者模式(Observer)(常用)

作者: jiahzhon | 来源:发表于2019-09-26 16:22 被阅读0次

- 定义

  • 指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
    功能:
    能够更好的梳理一对多的关系,还有对于松耦合的概念。使用观察者模式,至少我们能够切换对象在运行时是否能够被通知(更新消息等),简单来说,通过观察者模式,让我们对消息的更新更及时。

- 主要角色

  • 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
  • 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
  • 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
  • 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

- 结构图

observer.gif

- 使用场景

  • 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

- 代码实现

public class ObserverPattern
{
    public static void main(String[] args)
    {
        Subject subject=new ConcreteSubject();
        Observer obs1=new ConcreteObserver1();
        Observer obs2=new ConcreteObserver2();
        subject.add(obs1);
        subject.add(obs2);
        subject.notifyObserver();
    }
}
//抽象目标
abstract class Subject
{
    protected List<Observer> observers=new ArrayList<Observer>();   
    //增加观察者方法
    public void add(Observer observer)
    {
        observers.add(observer);
    }    
    //删除观察者方法
    public void remove(Observer observer)
    {
        observers.remove(observer);
    }   
    public abstract void notifyObserver(); //通知观察者方法
}
//具体目标
class ConcreteSubject extends Subject
{
    public void notifyObserver()
    {
        System.out.println("具体目标发生改变...");
        System.out.println("--------------");       
       
        for(Object obs:observers)
        {
            ((Observer)obs).response();
        }
       
    }          
}
//抽象观察者
interface Observer
{
    void response(); //反应
}
//具体观察者1
class ConcreteObserver1 implements Observer
{
    public void response()
    {
        System.out.println("具体观察者1作出反应!");
    }
}
//具体观察者1
class ConcreteObserver2 implements Observer
{
    public void response()
    {
        System.out.println("具体观察者2作出反应!");
    }
}

例子:
现在有一家气象站负责发布气象消息(WeatherData),作为不同的客户,会有不同的对于气象消息的需求,我们也就需要设计一个或者多个面向用户的消息面板获取气象总站的消息,并更新给用户满意的定制数据,用来获取报酬。

1569484997(1).jpg
观察者基本思路:
1569485319(1).jpg
对应到例子中:
1569485391(1).jpg
代码:
接口
public interface Subject {//主题接口
    public void registerObserver(Observer o);//注册
    public void removeObserver(Observer o);//删除
    public void notifyObservers();//主题状态改变,通知所有观察者
}
 
public interface Observer {//所有观察者必须实现Observer接口
    public void update(float temp, float humidity, float pressure);
}
 
public interface Display {//布告板需要显示时调用
    public void display();
}

实现subject的类--用一个List来维护观察者

public class WeatherData implements Subject{
    private ArrayList<Observer> observers;
    private float temp;
    private float humidity;
    private float pressure;
 
    public WeatherData() {
        observers = new ArrayList<Observer>();
    }
 
    @Override
    public void register(Observer o) {
        observers.add(o);
        
    }
 
    @Override
    public void remove(Observer o) {
        int i=observers.indexOf(o);
        if (i>=0) {//确认需要删除的观察者在队列中
            observers.remove(i);
        }
    }
 
    @Override
    public void notifys() {
        //刷新队列中所有已经注册的观察者
        for (int i = 0; i < observers.size(); i++) {
            observers.get(i).update(temp, humidity, pressure);
        }
    }
    
    public void weatherChanged() {
        //气象站得知消息更新时调用,更新观察者(布告板)
        notifys();
    }
    
    //主动刷新气象信息
    public void setWeather(float temperature, float humidity, float pressure) {
        this.temp = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        weatherChanged();
    }
 
    //单独获取气象信息的3个get方法
    public float getTemperature() {
        return temp;
    }
    
    public float getHumidity() {
        return humidity;
    }
    
    public float getPressure() {
        return pressure;
    }
 
}

公告板--观察者


public class Board1 implements Observer, Display{
    private float temp;
    private float humidity;
    private Subject weatherData;
    
    public Board1(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.register(this);
    }
    
    public void update(float temperature, float humidity, float pressure) {
        this.temp = temperature;
        this.humidity = humidity;
        display();//当气象信息改变立即刷新布告板
    }
    
    public void display() {
        System.out.println("Current conditions: " + temperature );
    }
}

测试类

public class WeatherTest {
 
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
    
        CurrentConditionsDisplay currentDisplay = new Board1 (weatherData);
 
        weatherData.setWeather(80, 65, 30.4f);
        weatherData.setWeather(82, 70, 29.2f);
        weatherData.setWeather(78, 90, 29.2f);
    }
}

java.util内包含Observerble类和Observer接口

1569485893(1).jpg
  1. 我们发现最大差异就是主题WeatherData只需要继承系统自带的Observable类。观察者通过Observer接口实现不变,改变的是通过addObserver()和deleteObserver方法进行注册和解绑。
  2. 主题发送通知,需要先调用setChange()方法,先声明状态的改变。然后调用notify方法进行刷新观察者状态。基本上与我们上面大同小异。

相关文章

网友评论

      本文标题:观察者模式(Observer)(常用)

      本文链接:https://www.haomeiwen.com/subject/xyhnuctx.html