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



我在这里问,只有当对象的特定属性发生变化时,我才需要通知观察者时,我应该如何处理这种情况。

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

区块报价明确指定感兴趣的修改。您可以通过扩展受试者的注册界面来提高更新效率,只允许为感兴趣的特定事件注册观察员。当此类事件发生时,受试者只通知那些对该事件感兴趣的观察者。支持这一点的一种方法是使用Subject对象的方面概念。为了记录对特定事件的兴趣,观察员使用与他们的受试者联系

void Subject::Attach(Observer*, Aspects 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);
.
.
.
}

有人能向我确认这是正确的方法吗?或者建议我更好的解决方案。

另一个选项是拥有一组接口:

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

最新更新