设计模式(二)java内置的观察者模式
2017-04-06 15:39
363 查看
概述
java.util包内包含最基本的Observer接口和Observable类,这和上一节的Observer接口与Subject接口很相似。Observer接口和Observable类使用上更方便。因为许多功能已经事先准备好了,甚至可以使用推(push)或拉(pull)的方式传递数据。但是Observable类也有一些黑暗面,有时候我们还是需要实现自己的主题接口。
UML
![](http://img.blog.csdn.net/20170406142054720?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaWZ3aW5kcw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
说明:
java内置的观察者模式与上一节介绍的观察者区别在于
1) Observable是一个类而不是一个接口,ConcreteSubject扩展了它并且继承了一系列增加、删除、通知等方法。Observable中添加了一个changed成员变量,和相关的setChanged()、clearChanged()、hasChanged()方法,用来标记状态的改变情况,当changed值为true时调用notifyObservers()方法才会更新观察者。(这样做是很有必要的,可以使设计更有弹性,我们可以在更适当的时候更新观察者)。
2) Observable类虽然提供了有用的功能但是它的实现也存在许多问题,限制了它的使用和复用。首先Observable是一个类而不是一个接口,并且它没有实现一个接口,我们必须设计一个类去继承它,如果某类需要同时具有Observable和另一个超类的行为,就会陷入两难,毕竟java不支持多重继承,这限制了Observable的复用潜力。再者Observable中状态相关的关键操作(例如setChanged()方法)是protected的,这意味着除非继承自Observable,否则我们无法创建Observable实例并组合到自己的对象中来。这个设计违反了“多用组合,少用继承”的设计原则。
3) Observer接口基本没有太大的改变,只是方法签名变了,如果想“推”数据给观察者,可以把数据当做数据对象传递给notifyObservers(arg)方法,否则观察者就必须从可观察者对象中“拉”数据(下面的实现是一个“拉”数据的例子)。
实现
运行结果:
![](http://img.blog.csdn.net/20170406142939797?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaWZ3aW5kcw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
参考资料:
《Head First设计模式》
java.util包内包含最基本的Observer接口和Observable类,这和上一节的Observer接口与Subject接口很相似。Observer接口和Observable类使用上更方便。因为许多功能已经事先准备好了,甚至可以使用推(push)或拉(pull)的方式传递数据。但是Observable类也有一些黑暗面,有时候我们还是需要实现自己的主题接口。
UML
说明:
java内置的观察者模式与上一节介绍的观察者区别在于
1) Observable是一个类而不是一个接口,ConcreteSubject扩展了它并且继承了一系列增加、删除、通知等方法。Observable中添加了一个changed成员变量,和相关的setChanged()、clearChanged()、hasChanged()方法,用来标记状态的改变情况,当changed值为true时调用notifyObservers()方法才会更新观察者。(这样做是很有必要的,可以使设计更有弹性,我们可以在更适当的时候更新观察者)。
2) Observable类虽然提供了有用的功能但是它的实现也存在许多问题,限制了它的使用和复用。首先Observable是一个类而不是一个接口,并且它没有实现一个接口,我们必须设计一个类去继承它,如果某类需要同时具有Observable和另一个超类的行为,就会陷入两难,毕竟java不支持多重继承,这限制了Observable的复用潜力。再者Observable中状态相关的关键操作(例如setChanged()方法)是protected的,这意味着除非继承自Observable,否则我们无法创建Observable实例并组合到自己的对象中来。这个设计违反了“多用组合,少用继承”的设计原则。
3) Observer接口基本没有太大的改变,只是方法签名变了,如果想“推”数据给观察者,可以把数据当做数据对象传递给notifyObservers(arg)方法,否则观察者就必须从可观察者对象中“拉”数据(下面的实现是一个“拉”数据的例子)。
实现
/** * 下面的实现省略了包名和这两个import操作 */ import java.util.Observable; import java.util.Observer;
/** * 子类-具体的可观察者(主题) */ public class ConcreteSubject extends Observable { private String message; /** * 更新消息 * 需要先调用setChanged()方法标记状态已经改变。 * 使用“拉”的方式:这里调用notifyObservers()没有传递数据对象。 */ public void messageChanged() { setChanged(); notifyObservers(); } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; messageChanged(); } }
/** * 接口实现类-具体的观察者 */ public class ConcreteObserver implements Observer { /** * 这里保存对subject的引用,是因为如果以后要取消注册, * 已经有了对subject的引用会比较方便。 */ private Observable observable; public ConcreteObserver(Observable o) { this.observable = o; observable.addObserver(this); } @Override public void update(Observable o, Object arg) { if (o instanceof ConcreteSubject) { ConcreteSubject ConcreteSubject = (ConcreteSubject) o; System.out.println(ConcreteSubject.getMessage()); } } }
/** * 测试类-观察者模式 */ public class ObserverTest { public static void main(String[] args) { ConcreteSubject concreteSubject = new ConcreteSubject(); Observer o1 = new ConcreteObserver(concreteSubject); Observer o2 = new ConcreteObserver(concreteSubject); Observer o3 = new ConcreteObserver(concreteSubject); concreteSubject.setMessage("Hello World !"); } }
运行结果:
参考资料:
《Head First设计模式》
相关文章推荐
- 设计模式 - 观察者模式(Observer Pattern) Java内置 使用方法
- 设计模式 - 观察者模式(Observer Pattern) Java内置 使用方法
- JAVA设计模式 之 观察者模式(JDK内置实现)
- Java中内置的设计模式-观察者模式
- Java设计模式2:观察者模式2(使用java内置的观察者)
- 设计模式 - 观察者模式(Observer Pattern) Java内置 用法
- java设计模式:观察者模式实例详解(基于java内置观察者)
- 设计模式-java内置观察者模式解析
- 设计模式之二:观察者模式(java内置(气象站模拟流程))
- Java设计模式(八)观察者模式 迭代器模式
- 观察者设计模式 Vs 事件委托(java)
- JAVA设计模式之观察者模式
- Java设计模式02--观察者模式
- Java设计模式学习笔记(观察者模式)
- Java设计模式之观察者模式
- Java设计模式(五) Observer(观察者)模式及Tomcat引申
- 设计模式:观察者模式(基于 Java)
- JAVA设计模式(观察者模式)
- Java设计模式_(行为型)_观察者模式
- 学习、探究Java设计模式——观察者模式