观察者 - 明确指定感兴趣的修改 - JAVA 实现

Observer - specifying modifications of interest explicitly - JAVA implementation

我问当我需要通知observers只有当[的特定属性时我应该如何处理这种情况=37=]对象变化。

我收到了关于 GoF 的非常好的回复,其中写道:

Blockquote Specifying modifications of interest explicitly. You can improve update efficiency by extending the subject's registration interface to allow registering observers only for specific events of interest. When such an event occurs, the subject informs only those observers that have registered interest in that event. One way to support this uses the notion of aspects for Subject objects. To register interest in particular events, observers are attached to their subjects using

void Subject::Attach(Observer*, Aspects interest);

Blockquote where interest specifies the event of interest. At notification time, the subject supplies the changed aspect to its observers as a parameter to the Update operation. For example:

void Observer::Update(Subject*, Aspect& interest);

这是有道理的,我想问一下如何在 Java 中正确实现它。我没有什么想法,但我不确定是否有更好的东西。

假设我有 subject class WeatherStation[temperature, humidity, windSpeed ...] 我有 observer class LimitedDisplay[show (shows only temperature and humidity) 出于某种原因,我需要显示器能够区分何时仅更改温度和仅更改湿度。

我在想我可以创建一些枚举 WeatherStationInterest[TEMPERATURE, HUMIDITY WIND_SPEED...] 然后拥有这样的主题界面:

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

有人可以向我确认这是正确的方法还是建议我更好的解决方案。

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

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

那么注册方法是这样的:

void registerListener(Object listener)

然后你会实现一个监听器:

class MyListener implements TemperatureListener, HumidityListener {
...
}

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

这是一个具有单个观察者界面和多个通知的实现。正如在上一个问题中评论的那样,我不是特别喜欢这个解决方案,因为我更喜欢用单独的接口命名观察者,而不是发送方法参数;但这显示了更少 类 与更多逻辑的权衡。

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);
    }
}