设计模式(十三)观察者模式(行为型)
观察者模式 Observer
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己。
观察者模式的组成
抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。
具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。
Code
//抽象观察者角色 public interface Watcher { public void update(String str); }
定义抽象的主题角色,即抽象的被观察者,在其中声明方法(添加、移除观察者,通知观察者):
//抽象主题角色,watched:被观察 public interface Watched { public void addWatcher(Watcher watcher); public void removeWatcher(Watcher watcher); public void notifyWatchers(String str); }
定义具体的观察者:
public class ConcreteWatcher implements Watcher { @Override public void update(String str) { System.out.println(str); } }
具体的主题角色:
import java.util.ArrayList; import java.util.List; public class ConcreteWatched implements Watched { // 存放观察者 private List<Watcher> list = new ArrayList<Watcher>(); @Override public void addWatcher(Watcher watcher) { list.add(watcher); } @Override public void removeWatcher(Watcher watcher) { list.remove(watcher); } @Override public void notifyWatchers(String str) { // 自动调用实际上是主题进行调用的 for (Watcher watcher : list) { watcher.update(str); } } }
编写测试类:
public class Test { public static void main(String[] args) { Watched girl = new ConcreteWatched(); Watcher watcher1 = new ConcreteWatcher(); Watcher watcher2 = new ConcreteWatcher(); Watcher watcher3 = new ConcreteWatcher(); girl.addWatcher(watcher1); girl.addWatcher(watcher2); girl.addWatcher(watcher3); girl.notifyWatchers("开心"); } }
Observable类
Observable类用于创建可以观测到你的程序中其他部分的子类。当这种子类的对象发生变化时,观测类被通知。
观测类必须实现定义了update()方法的Observer接口。
当一个观测程序被通知到一个被观测对象的改变时,update()方法被调用。
显然,Observable是一个抽象的主题对象。
一个被观测的对象必须服从下面的两个简单规则:
第一,如果它被改变了,它必须调用setChanged()方法。
第二,当它准备通知观测程序它的改变时,它必须调用notifyObservers()方法,这导致了在观测对象中对update()方法的调用。
注意:如果在调用notifyObservers()方法之前没有调用setChanged()方法,就不会有什么动作发生。
notifyObservers()方法中包含clearChanged()方法,将标志变量置回原值。
notifyObservers()方法采用的是从后向前的遍历方式,即最后加入的观察者最先被调用update()方法。
Code
定义一个主题对象进行倒数计数,数字每次改变时,它的观察者收到这个数字。
一个观察者每次收到通知后打印出数字,另一个观察者在数字小于等于5时才开始打印。
import java.util.Observable; import java.util.Observer; class WatchedCounter extends Observable { public void countdown(int number) { for (; number >= 0; --number) { // 设置改变变量 setChanged(); // 通知所有观察者,将number作为参数信息传递给观察者 notifyObservers(number); } } } class Watcher1 implements Observer { @Override public void update(Observable arg0, Object arg1) { System.out.println("Watcher1's number: " + arg1); } } class Watcher2 implements Observer { @Override public void update(Observable arg0, Object arg1) { if (((Integer) arg1).intValue() <= 5) { System.out.println("Watcher2's number: " + arg1); } } } public class ObserverTest { public static void main(String[] args) { WatchedCounter watchedCounter = new WatchedCounter(); Watcher1 watcher1 = new Watcher1(); Watcher2 watcher2 = new Watcher2(); //添加观察者 watchedCounter.addObserver(watcher1); watchedCounter.addObserver(watcher2); //开始倒数计数 watchedCounter.countdown(10); } }
我是天王盖地虎的分割线
参考:http://www.cnblogs.com/mengdd/archive/2013/02/08/2909206.html
出处:http://yydcdut.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?