在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

Java设计模式开发中使用观察者模式的实例教程

2016-7-29 15:37| 发布者: zhangjf| 查看: 642| 评论: 0

摘要: 观察者模式是软件设计模式中的一种,使用也比较普遍,尤其是在GUI编程中。关于设计模式的文章,网络上写的都比较多,而且很多文章写的也不错,虽然说有一种重复早轮子的嫌疑,但此轮子非彼轮子,侧重点不同,思路也 ...

观察者模式是软件设计模式中的一种,使用也比较普遍,尤其是在GUI编程中。关于设计模式的文章,网络上写的都比较多,而且很多文章写的也不错,虽然说有一种重复早轮子的嫌疑,但此轮子非彼轮子,侧重点不同,思路也不同,讲述方式也不近相同。
关键要素

主题:

主题是观察者观察的对象,一个主题必须具备下面三个特征。

  • 持有监听的观察者的引用
  • 支持增加和删除观察者
  • 主题状态改变,通知观察者

观察者:

当主题发生变化,收到通知进行具体的处理是观察者必须具备的特征。

为什么要用这种模式

这里举一个例子来说明,牛奶送奶站就是主题,订奶客户为监听者,客户从送奶站订阅牛奶后,会每天收到牛奶。如果客户不想订阅了,可以取消,以后就不会收到牛奶。

松耦合

观察者增加或删除无需修改主题的代码,只需调用主题对应的增加或者删除的方法即可。
主题只负责通知观察者,但无需了解观察者如何处理通知。举个例子,送奶站只负责送递牛奶,不关心客户是喝掉还是洗脸。
观察者只需等待主题通知,无需观察主题相关的细节。还是那个例子,客户只需关心送奶站送到牛奶,不关心牛奶由哪个快递人员,使用何种交通工具送达。

Java实现观察者模式
1. Java自带的实现
类图

201642494900291.jpg (806×524)

  1. /**
  2. * 观察目标 继承自 java.util.Observable
  3. * @author stone
  4. *
  5. */
  6. public class UpdateObservable extends Observable {
  7. private int data;
  8. public UpdateObservable(Observer observer) {
  9. addObserver(observer);
  10. /*
  11. * add other observer
  12. */
  13. }
  14. public int getData() {
  15. return data;
  16. }
  17. public void setData(int data) {
  18. if (data != this.data) {
  19. this.data = data;
  20. setChanged(); //标记 改变, 只有标记后才能通知到
  21. notifyObservers(); //通知
  22. }
  23. }
  24. @Override
  25. public synchronized void addObserver(Observer o) {
  26. super.addObserver(o);
  27. }
  28. @Override
  29. public synchronized void deleteObserver(Observer o) {
  30. super.deleteObserver(o);
  31. }
  32. @Override
  33. public void notifyObservers() {
  34. super.notifyObservers();
  35. }
  36. @Override
  37. public void notifyObservers(Object arg) {
  38. super.notifyObservers(arg);
  39. }
  40. @Override
  41. public synchronized void deleteObservers() {
  42. super.deleteObservers();
  43. }
  44. @Override
  45. protected synchronized void setChanged() {
  46. super.setChanged();
  47. }
  48. @Override
  49. protected synchronized void clearChanged() {
  50. super.clearChanged();
  51. }
  52. @Override
  53. public synchronized boolean hasChanged() {
  54. return super.hasChanged();
  55. }
  56. @Override
  57. public synchronized int countObservers() {
  58. return super.countObservers();
  59. }
  60. }
复制代码
  1. /**
  2. * 观察者 实现 java.util.Observer接口
  3. * @author stone
  4. *
  5. */
  6. public class UpdateObserver implements Observer {
  7. @Override
  8. public void update(Observable o, Object arg) {
  9. System.out.println("接收到数据变化的通知:");
  10. if (o instanceof UpdateObservable) {
  11. UpdateObservable uo = (UpdateObservable) o;
  12. System.out.print("数据变更为:" + uo.getData());
  13. }
  14. }
  15. }
复制代码

2. 自定义的观察模型
类图

201642494952492.jpg (968×676)

  1. /**
  2. * 抽象观察者 Observer
  3. * 观察 更新
  4. * @author stone
  5. *
  6. */
  7. public interface IWatcher {
  8. /*
  9. * 通知接口:
  10. * 1. 简单通知
  11. * 2. 观察者需要目标的变化的数据,那么可以将目标用作参数, 见Java的Observer和Observable
  12. */
  13. // void update(IWatched watched);
  14. void update();
  15. }
复制代码
  1. /**
  2. * 抽象目标 Subject
  3. * 提供注册和删除观察者对象的接口, 及通知观察者进行观察的接口
  4. * 及目标 自身被观察的业务的接口
  5. * @author stone
  6. *
  7. */
  8. public interface IWatchedSubject {
  9. public void add(IWatcher watch);
  10. public void remove(IWatcher watch);
  11. public void notifyWhatchers();
  12. public void update();//被观察业务变化的接口
  13. }
复制代码
  1. /**
  2. * 具体观察者 Concrete Observer
  3. *
  4. * @author stone
  5. *
  6. */
  7. public class UpdateWatcher implements IWatcher {
  8. @Override
  9. public void update() {
  10. System.out.println(this + "观察到:目标已经更新了");
  11. }
  12. }
复制代码


  1. /**
  2. * 具体目标角色 Concrete Subject
  3. * @author stone
  4. *
  5. */
  6. public class UpdateWatchedSubject implements IWatchedSubject {
  7. private List<IWatcher> list;
  8. public UpdateWatchedSubject() {
  9. this.list = new ArrayList<IWatcher>();
  10. }
  11. @Override
  12. public void add(IWatcher watch) {
  13. this.list.add(watch);
  14. }
  15. @Override
  16. public void remove(IWatcher watch) {
  17. this.list.remove(watch);
  18. }
  19. @Override
  20. public void notifyWhatchers() {
  21. for (IWatcher watcher : list) {
  22. watcher.update();
  23. }
  24. }
  25. @Override
  26. public void update() {
  27. System.out.println("目标更新中....");
  28. notifyWhatchers();
  29. }
  30. }
复制代码


监听器是观察者的一种实现:
类图

201642495137152.jpg (780×502)

  1. /**
  2. * 监听 用户在注册后
  3. * @author stone
  4. *
  5. */
  6. public interface IRegisterListener {
  7. void onRegistered();
  8. }
复制代码
  1. /**
  2. * 监听 当用户登录后
  3. * @author stone
  4. *
  5. */
  6. public interface ILoginListener {
  7. void onLogined();
  8. }
复制代码
  1. /*
  2. * 监听器 是观察者模式的一种实现
  3. * 一些需要监听的业务接口上添加 监听器,调用监听器的相应方法,实现监听
  4. */
  5. public class User {
  6. public void register(IRegisterListener register) {
  7. /*
  8. * do ... register
  9. */
  10. System.out.println("正在注册中...");
  11. //注册后
  12. register.onRegistered();
  13. }
  14. public void login(ILoginListener login) {
  15. /*
  16. * do ... login
  17. */
  18. System.out.println("正在登录中...");
  19. //登录后
  20. login.onLogined();
  21. }
  22. }
复制代码


  1. /**
  2. * 观察者(Observer)模式 行为型模式
  3. * 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时观察某一个目标对象。
  4. * 这个目标对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己
  5. * 目标对象中需要有添加、移除、通知 观察者的接口
  6. *
  7. * @author stone
  8. */
  9. public class Test {
  10. public static void main(String[] args) {
  11. /*
  12. * 使用Java自带的Observer接口和Observable类
  13. */
  14. UpdateObservable observable = new UpdateObservable(new UpdateObserver());
  15. observable.setData(99);
  16. System.out.println("");
  17. System.out.println("");
  18. /*
  19. * 自定义的观察者模型
  20. */
  21. IWatchedSubject watched = new UpdateWatchedSubject();
  22. watched.add(new UpdateWatcher());
  23. watched.add(new UpdateWatcher());
  24. watched.update();
  25. System.out.println("");
  26. /*
  27. * 子模式-监听器
  28. */
  29. User user = new User();
  30. user.register(new IRegisterListener() {
  31. @Override
  32. public void onRegistered() {
  33. System.out.println("监听到注册后。。。");
  34. }
  35. });
  36. user.login(new ILoginListener() {
  37. @Override
  38. public void onLogined() {
  39. System.out.println("监听到登录后。。。");
  40. }
  41. });
  42. }
  43. }
复制代码


打印

  1. 接收到数据变化的通知:
  2. 数据变更为:99
  3. 目标更新中....
  4. observer.UpdateWatcher@457471e0观察到:目标已经更新了
  5. observer.UpdateWatcher@5fe04cbf观察到:目标已经更新了
  6. 正在注册中...
  7. 监听到注册后。。。
  8. 正在登录中...
  9. 监听到登录后。。。
复制代码

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-5-6 09:10

Copyright 2015-2025 djqfx

返回顶部