观察者-显式指定感兴趣的修改-java实现

6ie5vjzr  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(289)

我在这里问,当我只需要在对象的特定属性改变时通知观察者时,我应该如何处理这种情况。
我收到了关于gof的非常好的回复,其中写道:
明确指定感兴趣的修改的blockquote。您可以通过扩展主题的注册接口来提高更新效率,以便只允许为感兴趣的特定事件注册观察者。当此类事件发生时,受试者仅通知对该事件感兴趣的观察者。支持这一点的一种方法是使用主客体方面的概念。为了记录对特定事件的兴趣,观察者会使用 void Subject::Attach(Observer*, Aspects interest); blockquote,其中interest指定感兴趣的事件。在通知时,主体将更改的方面作为更新操作的参数提供给其观察者。例如: void Observer::Update(Subject*, Aspect& interest); 这是有意义的,我想问一下如何在java中正确地实现这一点。我没有什么主意,但我不确定是否有更好的办法。
让我们假设我有科目课 WeatherStation[temperature, humidity, windSpeed ...] 我有观察家班 LimitedDisplay[show (shows only temperature and humidity) 出于某种原因,我需要显示器能够区分什么时候只有温度变化,什么时候只有湿度变化。
我在想我可以创建一些枚举 WeatherStationInterest[TEMPERATURE, HUMIDITY WIND_SPEED...] 然后主题界面如下:

public interface WeatherStationSubject{
    registerObserver(WeatherStationObserver observer, WeatherStationInterest... interests);
    .
    .
    .
}

有人能确认我,这是正确的方式做它或建议我更好的解决办法。

3xiyfsfu

3xiyfsfu1#

这是一个具有单个观察者接口和多个通知的实现。如前一个问题中所述,我并不特别喜欢这个解决方案,因为我更喜欢用单独的接口命名观察者,而不是发送方法参数;但这显示了用更少的类来换取更多逻辑的折衷。

public class Main {
    enum ObservableValue {
        TEMP, HUMIDITY, WIND
    }

    interface Observer {
        void notify(ObservableValue changed);
    }

    static class LimitedDisplay implements Observer {
        @Override
        public void notify(ObservableValue changed) {
            System.out.println(changed + " has changed.");
        }
    }

    static class WeatherStation {
        private double temp;
        private double humidity;
        private double wind;

        private final Map<ObservableValue, Set<Observer>> observers = new EnumMap<>(ObservableValue.class);

        WeatherStation() {
            Arrays.stream(ObservableValue.values()).forEach(value -> observers.put(value, new HashSet<>()));
        }

        void register(Observer observer, ObservableValue... values) {
            Arrays.stream(values).forEach(value -> observers.get(value).add(observer));
        }

        void setTemp(double temp) {
            this.temp = temp;
            observers.get(TEMP).forEach(observer -> observer.notify(TEMP));
        }

        void setHumidity(double humidity) {
            this.humidity = humidity;
            observers.get(HUMIDITY).forEach(observer -> observer.notify(HUMIDITY));
        }

        void setWind(double wind) {
            this.wind = wind;
            observers.get(WIND).forEach(observer -> observer.notify(WIND));
        }
    }

    public static void main(String[] args) {
        WeatherStation ws = new WeatherStation();
        ws.register(new LimitedDisplay(), ObservableValue.values());
        ws.setTemp(1.2);
        ws.setHumidity(3.4);
        ws.setWind(5.6);
    }
}
jm81lzqq

jm81lzqq2#

另一种选择是拥有一组接口:

interface TemperatureListener {
    onTemperatureChange(double newTemperature);
}
interface HumidityListener {
    onHumidityChange(double newHumidity);
}
...

然后,注册方法如下所示:

void registerListener(Object listener)

你要实现一个监听器:

class MyListener implements TemperatureListener, HumidityListener {
...
}

不一定更好,但如果这很重要的话,可以很容易地看到实际发生了什么变化。

相关问题