出版者+订阅者=观察者模式
出版者:主题 Subject
订阅者:观察者 Observer
观察者模式
在对象之间定义一对多的依赖关系,当一个对象(主题)改变状态时,它的所有依赖者(观察者)都将收到通知,并自动更新。
主题与观察者之间通过组合关系完成相互的调用:
所有观察者Observer持有相同的一个主题Subject,观察者通过该接口向主题进行注册;
主题Subject持有观察者的一个集合List<Observer>,主题遍历集合向每个观察者发送通知
设计原则
为了交互对象之间的松耦合设计而努力;
找出程序中会变化的方面,然后将其和固定不变的方面相分离。(观察者的类型和个数是变化的);
针对接口编程,不针对实现编程。(主题与观察者都是接口,主题也可以有多个实现);
多用组合,少用继承。(通过依赖完成关系的建立);
================================================================================
实例
主题接口
package Subject; import Observer.Observer; public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); }
具体的主题
package Subject; import java.util.ArrayList; import java.util.List; import Observer.Observer; public class WeatherData implements Subject { private float temperature; private float humidity; private float pressure; //一对多关系 //观察者的集合 private List<Observer> observers; public WeatherData() { this.observers = new ArrayList<Observer>(); } /** * 注册到主题中 */ @Override public void registerObserver(Observer o) { this.observers.add(o); } /** * 取消订阅 */ @Override public void removeObserver(Observer o) { int index = this.observers.indexOf(o); if(index!=-1) this.observers.remove(o); } /** * 一旦状态发生变化,通知所有的观察者 */ @Override public void notifyObservers() { for(Observer o : observers) o.update(temperature, humidity, pressure); } public void measurementChanged() { notifyObservers(); } public void setMessurements(float temprature, float humidity, float pressure) { this.temperature = temprature; this.humidity = humidity; this.pressure = pressure; measurementChanged(); } }
观察者的接口
package Observer; public interface Observer { /** * 观察者提供给主题使用的接口 */ public void update(float temp, float humidity, float pressure); }
观察者需要实现的另一个接口-布告栏接口
package display; public interface DisplayElement { public void display(); }
具体的观察者
package Observer; import Subject.Subject; import display.DisplayElement; public class CurrentConditionDisplay implements Observer, DisplayElement { private float temperature; private float humidity; //持有主题的引用,完成对主题的注册与取消订阅 private Subject weatherData; public CurrentConditionDisplay(Subject weatherData) { this.weatherData = weatherData; //注册 this.weatherData.registerObserver(this); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; display(); } @Override public void display() { System.out.println("Current Condition: tempratute="+temperature+", humidity="+humidity); } }
package Observer; import Subject.Subject; import display.DisplayElement; public class StatisticsDisplay implements Observer, DisplayElement { private float temperature; private float humidity; //持有主题的引用,完成对主题的注册与取消订阅 private Subject weatherData; public StatisticsDisplay(Subject weatherData) { this.weatherData = weatherData; //注册 this.weatherData.registerObserver(this); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; display(); } @Override public void display() { System.out.println("StatisticsDisplay: tempratute="+temperature+", humidity="+humidity); } }
package Observer; import Subject.Subject; import display.DisplayElement; public class ForeastDisplay implements Observer, DisplayElement { private float temperature; private float humidity; //持有主题的引用,完成对主题的注册与取消订阅 private Subject weatherData; public ForeastDisplay(Subject weatherData) { this.weatherData = weatherData; //注册 this.weatherData.registerObserver(this); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; display(); } @Override public void display() { System.out.println("ForeastDisplay: tempratute="+temperature+", humidity="+humidity); } }
测试
package test; import Observer.CurrentConditionDisplay; import Observer.ForeastDisplay; import Observer.StatisticsDisplay; import Subject.WeatherData; public class WeatherDataTest { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay(weatherData); StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); ForeastDisplay foreastDisplay = new ForeastDisplay(weatherData); weatherData.setMessurements(31.03f, 29.33f, 100.21f); //取消订阅的职责是否应该放到观察者中进行更合适? weatherData.removeObserver(foreastDisplay); System.out.println("remove foreastDisplay..."); weatherData.setMessurements(22.03f, 33.33f, 44.21f); } }
================================================================================
使用JAVA内置的观察者模式
Observable的黑暗面---Observable是一个类而不是一个接口,它甚至没有实现一个接口。
如果要使用JAVA提供的这个Observable的行为,只能通过继承才能得到,这样便让子类非常的为难,最终限制了Observable的复用潜力。
setChanged()在Observable类中被保护起来了,除非继承Observable,否则无法创建Observable实例并组合到自己的对象中。
在子类中,通过Observable类中protected权限的setChanged()方法,去改变Observable类中的私有属性boolean changed = true,完成状态的切换!!!
主题
package Subject; import java.util.Observable; /** * 主题 * 主题继承JAVA提供的内置主题 * 由于JAVA提供的Observable是一个类,要想使用JAVA内置的这个功能,只能采用继承 * */ public class WeatherData2 extends Observable { private float temperature; private float humidity; private float pressure; public void measurementChanged() { //指示状态已发生变化,可以通知观察者了。扩展点:这里可以设置条件,当条件满足时才发出通知,而不是每次变化都通知! setChanged(); //通知所有的观察者 notifyObservers(); } public void setMessurements(float temprature, float humidity, float pressure) { this.temperature = temprature; this.humidity = humidity; this.pressure = pressure; measurementChanged(); } public float getTemperature() { return temperature; } public float getHumidity() { return humidity; } public float getPressure() { return pressure; } }
观察者需要实现的布告栏接口
package display; public interface DisplayElement { public void display(); }
观察者
package Observer; import java.util.Observable; import java.util.Observer; import Subject.WeatherData2; import display.DisplayElement; /** * 观察者 * 使用JAVA提供的内置观察者接口 * */ public class CurrentConditionDisplay2 implements Observer, DisplayElement { //主题接口 Observable observable; private float temperature; private float humidity; public CurrentConditionDisplay2(Observable observable){ //为主题接口指定具体实现类 this.observable = observable; //将观察者注册到主题中 this.observable.addObserver(this); } /** * 采用拉的方式,由观察者自己到主题中获取需要的数据 * @param o 主题 * @param arg 主题“推送”的数据,如果不为空,则表示由主题负责“推送”数据 */ @Override public void update(Observable o, Object arg) { if(o instanceof WeatherData2) { WeatherData2 wd = (WeatherData2)o; this.temperature = wd.getTemperature(); this.humidity = wd.getHumidity(); display(); } } @Override public void display() { System.out.println("Current Condition: tempratute="+temperature+", humidity="+humidity); } }
测试
package test; import Observer.CurrentConditionDisplay2; import Subject.WeatherData2; public class WeatherData2Test { public static void main(String[] args) { WeatherData2 weatherData = new WeatherData2(); CurrentConditionDisplay2 currentDisplay = new CurrentConditionDisplay2(weatherData); weatherData.setMessurements(31.03f, 29.33f, 100.21f); //取消订阅的职责是否应该放到观察者中进行更合适? weatherData.deleteObserver(currentDisplay); System.out.println("remove foreastDisplay..."); weatherData.setMessurements(22.03f, 33.33f, 44.21f); } }
相关推荐
《Head First 之观察者模式》是一本深入浅出介绍观察者模式的书籍,通过生动有趣的方式帮助读者理解和掌握这一设计模式。观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生...
在Head First的设计模式系列书籍中,作者通过易懂且生动的方式介绍了观察者模式。观察者模式的核心思想是“发布-订阅”机制,它将观察目标(被观察者)和观察者(订阅者)解耦,使得两者可以独立地变化。这种模式的...
观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多...在`head first 设计模式`的讲解中,读者将能深入理解如何在C++中有效地应用观察者模式,并掌握其在实际项目中的使用技巧。
HeadFirst的设计模式系列书籍以其直观易懂的方式深受程序员喜爱,本笔记将深入探讨观察者模式的概念及其应用。 观察者模式的核心思想是定义对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的...
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 Observer Pattern defines a one-to-many dependency between objects so that when one object ...
3. **观察者模式**(Observer):定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。Java中的`java.util.Observable`和`java.util.Observer`接口就是这种...
总之,HeadFirst设计模式中的"Observer"部分将帮助读者深入理解观察者模式,并提供C++实现的实例,使读者能够将这一模式应用于实际项目中,提升软件设计的灵活性和可维护性。通过学习这个模式,开发者可以更好地理解...
行为型模式涉及对象间的交互和责任分配,包括模板方法模式(Template Method)、观察者模式(Observer)、策略模式(Strategy)、职责链模式(Chain of Responsibility)、命令模式(Command)、迭代器模式...
行为型模式涉及对象之间的责任分配,包括模板方法模式(Template Method)、策略模式(Strategy)和观察者模式(Observer)。模板方法模式定义了一个操作中的算法骨架,允许子类在其间填充具体步骤;策略模式定义一...
行为型模式则主要处理对象之间的交互和责任分配,例如策略模式(Strategy)、观察者模式(Observer)和职责链模式(Chain of Responsibility)等,它们有助于实现灵活、可扩展的行为。 《Head First设计模式》书中...
在描述中提到的"Head First模式设计用的是Java",可能是指书中通过Java语言讲解了观察者模式的基本概念和实现方式,而"实现观察者模式使用C++"则意味着我们将讨论如何在C++环境中实现同样的设计模式。 观察者模式的...
行为型模式如策略(Strategy)、观察者(Observer)、装饰器(Decorator)和模板方法(Template Method)等,则关注对象间的行为协作。 每章结束时,书中还包含了要点整理和习题,帮助读者复习和巩固知识点。通过...
这里以一个天气监测应用程序作为案例,介绍观察者模式(Observer Pattern)。观察者模式是一种行为设计模式,允许对象之间维持一对多的依赖关系,当一个对象改变状态时,所有依赖于它的对象都会收到通知并自动更新。...
11. 观察者模式(Observer):定义对象间的一种一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。观察者模式广泛应用于事件驱动编程和发布/订阅模型。 每个模式的案例都...
Java中,`java.util.Observer` 和 `java.util.Observable` 类就是观察者模式的实现。 12. 状态模式:允许对象在其内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式常用于管理对象的不同状态下的...
行为型模式则主要关注对象之间的交互和责任分配,如观察者模式(Observer)、策略模式(Strategy)和职责链模式(Chain of Responsibility)等。 在《HeadFirst设计模式源代码》的源码中,你可以找到这些模式的实际...
3. **行为型模式**:包括策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、迭代器模式(Iterator)、命令模式(Command)、备忘录模式(Memento)、状态模式(State)、访问者模式...
- 观察者模式(Observer):定义对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。 - 策略模式(Strategy):定义了一系列算法,并将每个算法封装起来,使...