来聊聊观察者模式

作为最简单的设计模式,观察者也是应用的相当广泛,看看官方是怎么说的:

观察者模式:定义了对象一对多的依赖,这样一来,当对象改变时,它的所有依赖者都会受到通知并自动更新。

下面考虑一个气象站的例子来实现观察者模式,气象指数一旦有变化,分布在两个地方的显示屏实时更新,考虑以下:

1.一旦气象站数据有更新,观察者(负责显示的设备)必须第一时间知道,而且通知的方式不是观察者向数据源索取,观察者没有那么多精力,数据源有义务一旦数据更新立刻通知观察者

2.数据源weatherdata只有一个,但是观察者有很多个,并且观察者并不是都是一模一样,后续完全可能增加或者删除一个或多个观察者。

3.当我不想观察这个数据,可以动态的取消一个观察者,增加也是一样,原则就是保持流动性

首先定义数据源(主题),为了保持数据的抽象,考虑使用接口:

public interface Info {
    void addObserver(InfoObserver observer);
    void removeObserver(InfoObserver observer);
    void notifyObserver();
}

天气数据要实现此接口:


public class WeatherInfo implements Info{

    private int temperature;
    private String pollution;
    private List<InfoObserver> observers;

    private static final String TAG = "WeatherInfo";

    public void setTemperature(int temperature) {
        if(this.temperature!=temperature)
        this.temperature = temperature;
        notifyObserver();
    }


    public void setPollution(String pollution) {
        if(!this.pollution.equals(pollution)){
            this.pollution = pollution;
            notifyObserver();
        }

    }

    public WeatherInfo(int temperature,String pollution){
        this.temperature = temperature;
        this.pollution = pollution;
        observers = new ArrayList<>();
    }

    @Override
    public void addObserver(InfoObserver observer) {
        if(!observers.contains(observer)){
            observers.add(observer);
            Log.d(TAG,"增加观察者 "+observer.getClass().toString());
        }
    }

    @Override
    public void removeObserver(InfoObserver observer) {
        if(observers.contains(observer)){
            observers.remove(observer);
        }
    }

    @Override
    public void notifyObserver() {
        for(InfoObserver observer: observers){
            observer.update(temperature,pollution);
        }
    }
}

而观察者,显然也应有对应的抽象,想怎么显示,不同的观察者应该会不同:

public interface InfoObserver {

    void update(int temperature,String pollution);
}

先建立一个观察者,此观察者只对温度感兴趣:

public class TemperatureObserver implements InfoObserver{
    private Info info;

    private static final String TAG = "TemperatureObserver";

    public TemperatureObserver(Info info){
        this.info = info;
        info.addObserver(this);
    }
    @Override
    public void update(int temperature,String pollution) {
        Log.d(TAG,"当前温度: "+temperature);
    }
}

这里有另外一个观察者,对污染程度感兴趣:

public class PollutionObserver implements InfoObserver{
    private Info info;

    public PollutionObserver(Info info){
        this.info = info;
        info.addObserver(this);
    }

    private static final String TAG = "PollutionObserver";
    @Override
    public void update(int temperature, String pollution) {
        Log.d(TAG,"当前污染程度: "+pollution);
    }
}

来看测试代码:

        WeatherInfo weatherInfo  = new WeatherInfo(17,"slight");
        InfoObserver weatherObserver = new TemperatureObserver(weatherInfo);
        weatherInfo.setTemperature(26);
        InfoObserver pollutionObserver = new PollutionObserver(weatherInfo);
        weatherInfo.setPollution("serious");

运行结果如下:

11-17 11:33:31.670 26070-26070/com.poxy D/WeatherInfo: 增加观察者 class com.oberveser.TemperatureObserver
11-17 11:33:31.670 26070-26070/com.poxy D/TemperatureObserver: 当前温度: 26
11-17 11:33:31.671 26070-26070/com.poxy D/WeatherInfo: 增加观察者 class com.oberveser.PollutionObserver
11-17 11:33:31.671 26070-26070/com.poxy D/TemperatureObserver: 当前温度: 26
11-17 11:33:31.671 26070-26070/com.poxy D/PollutionObserver: 当前污染程度: serious

其优点有:
1.数据源(主题)真正拥有这些数据并且能控制他们,比起让许多对象控制同一份数据,可以得到更干净的OO设计。两个对象松耦合,他们之间交互,但是不太清楚彼此细节

2.有新的观察者出现,主题代码不需要修改,只要新的观察者去实现observer接口,然后注册即可,改变主题或者观察者,并不影响另外一方,只要他们之间的接口仍然被遵守。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值