赞
踩
在软件系统中,对象之间往往需要相互依赖。例如,视图对象依赖于数据模型对象,来显示最新的数据状态。直接的依赖关系会导致高耦合,增加维护的复杂性和难度。
设计初衷:
示例:
一个天气预报系统中,WeatherData
类作为被观察者,而CurrentConditionsDisplay
、StatisticsDisplay
等作为观察者。WeatherData
不需要了解具体显示类的实现,只需知道它们实现了Observer
接口。
在运行时,系统的依赖关系可能需要动态变化。例如,用户可能会在运行时订阅或取消订阅某些数据。
设计初衷:
示例:
在一个股票交易系统中,用户可以随时订阅或取消订阅股票行情。StockData
类作为被观察者,当用户订阅时,将其客户端注册为观察者,当用户取消订阅时,将其从观察者列表中移除。
在一些实时更新的系统中,依赖对象需要在状态变化时自动更新。例如,当数据模型改变时,视图对象需要自动更新以反映最新的数据。
设计初衷:
示例:
在一个气象站应用中,当气象数据变化时,WeatherData
会通知所有的显示组件(观察者),以便它们更新显示最新的气象数据。
问题:
在软件系统中,不同的对象之间往往存在依赖关系。例如,一个数据模型对象(Model)和多个视图对象(View)。当数据模型发生变化时,视图对象需要随之更新。如果每个视图对象都直接依赖于数据模型对象,并且在数据模型中直接调用视图对象的方法,这将导致系统的高耦合,增加维护难度。
解决方案:
通过观察者模式,被观察者(Subject)和观察者(Observer)之间的关系是松耦合的。被观察者只知道有一组观察者实现了某个接口,而不知道具体是什么对象。观察者也只知道被观察者的状态发生了变化,而不知道变化的具体原因。这样就实现了对象之间的解耦。
示例:
在一个气象站应用中,气象数据(WeatherData)是被观察者,而各种显示元素(如当前条件显示、统计显示等)是观察者。气象数据只需要通知观察者数据发生了变化,而具体如何显示是观察者的事情。
问题:
系统在运行时可能需要动态地添加或移除依赖关系。例如,在一个实时股票行情系统中,不同的客户端可能在不同的时间段订阅或取消订阅股票行情。
解决方案:
观察者模式允许在运行时动态地注册(添加)或注销(移除)观察者。这使得系统能够灵活地响应不同的需求和变化,而无需在设计时确定所有的依赖关系。
示例:
在一个聊天应用中,当用户加入一个群组时,用户的客户端会成为群组消息的观察者。当用户离开群组时,用户的客户端会被移除出群组消息的观察者列表。
问题:
当一个对象的状态变化时,依赖它的所有对象需要同步更新。例如,在一个数据驱动的应用中,当数据模型变化时,所有依赖于该模型的视图都需要更新。
解决方案:
通过观察者模式,当被观察者的状态发生变化时,它会通知所有注册的观察者进行更新。这样,所有依赖于被观察者的对象都能够自动更新,保持系统的一致性。
示例:
在一个股票交易应用中,当股票价格变化时,所有显示该股票价格的视图都会自动更新,以显示最新的价格。
import java.util.ArrayList; import java.util.List; public interface Subject { void registerObserver(Observer o); void removeObserver(Observer o); void notifyObservers(); } class WeatherData implements Subject { private List<Observer> observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList<>(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { observers.remove(o); } @Override public void notifyObservers() { for (Observer observer : observers) { observer.update(temperature, humidity, pressure); } } public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } public void measurementsChanged() { notifyObservers(); } }
public interface Observer { void update(float temperature, float humidity, float pressure); } class CurrentConditionsDisplay implements Observer { private float temperature; private float humidity; private Subject weatherData; public CurrentConditionsDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void update(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; display(); } public void display() { System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity"); } }
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}
Subject(被观察者/主题):
Observer(观察者):
+----------+ +-----------+
| Subject |<------>| Observer |
+----------+ +-----------+
| attach() | | update() |
| detach() | +-----------+
| notify() |
+----------+
Java 提供了内置的 java.util.Observable
类和 java.util.Observer
接口。
import java.util.Observable; public class WeatherData extends Observable { private float temperature; private float humidity; private float pressure; public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } public void measurementsChanged() { setChanged(); notifyObservers(); } public float getTemperature() { return temperature; } public float getHumidity() { return humidity; } public float getPressure() { return pressure; } }
import java.util.Observable; import java.util.Observer; public class CurrentConditionsDisplay implements Observer { private float temperature; private float humidity; public CurrentConditionsDisplay(Observable observable) { observable.addObserver(this); } @Override public void update(Observable obs, Object arg) { if (obs instanceof WeatherData) { WeatherData weatherData = (WeatherData) obs; this.temperature = weatherData.getTemperature(); this.humidity = weatherData.getHumidity(); display(); } } public void display() { System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity"); } }
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}
在现代Java编程中,更推荐使用自定义接口和类实现观察者模式,因为 java.util.Observable
已被标记为过时。
import java.util.ArrayList; import java.util.List; public interface Subject { void registerObserver(Observer o); void removeObserver(Observer o); void notifyObservers(); } class WeatherData implements Subject { private List<Observer> observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList<>(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { int i = observers.indexOf(o); if (i >= 0) { observers.remove(i); } } @Override public void notifyObservers() { for (Observer observer : observers) { observer.update(temperature, humidity, pressure); } } public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } public void measurementsChanged() { notifyObservers(); } }
public interface Observer { void update(float temp, float humidity, float pressure); } class CurrentConditionsDisplay implements Observer { private float temperature; private float humidity; @Override public void update(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; display(); } public void display() { System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity"); } }
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
weatherData.registerObserver(currentDisplay);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}
松耦合:
动态注册和注销:
自动通知:
通知顺序不确定:
内存泄漏:
性能问题:
观察者模式的设计初衷主要在于解决对象之间的耦合问题,允许动态依赖关系,并自动通知依赖对象进行更新。这些特性使得观察者模式在需要松耦合、动态依赖和自动更新的场景中非常有用。然而,开发者在使用观察者模式时,也需要注意内存泄漏、性能开销等问题,采取适当的优化措施,如使用弱引用和异步通知,来提升系统的健壮性和效率。
通过合理使用观察者模式,可以使系统更加灵活、可维护性更高,并且能够有效地响应变化。这种模式在GUI应用、实时数据更新、发布-订阅系统等场景中得到了广泛应用,是软件设计中的重要模式之一。
欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。