经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
Java中常用的设计模式之观察者模式详解
来源:jb51  时间:2022/2/28 8:51:27  对本文有异议

优点

1.观察者和被观察者是抽象耦合的。

2.建立一套触发机制。

缺点

1.如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

2.如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

3.观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景

一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。

一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。

一个对象必须通知其他对象,而并不知道这些对象是谁。

需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

注意事项

1.JAVA 中已经有了对观察者模式的支持类。

2.避免循环引用。

3.如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

一、实现方式

1、观察者抽象类

  1. package com.asurplus.common.observe;
  2. /**
  3. * 观察者
  4. */
  5. public abstract class Observer {
  6. protected Subject subject;
  7. /**
  8. * 发布事件
  9. */
  10. public abstract void update();
  11. }

2、第一个观察者

  1. package com.asurplus.common.observe;
  2. import lombok.extern.slf4j.Slf4j;
  3. @Slf4j
  4. public class Observer1 extends Observer {
  5. public Observer1(Subject subject) {
  6. this.subject = subject;
  7. this.subject.attach(this);
  8. }
  9. @Override
  10. public void update() {
  11. log.info("观察者 1 收到通知:{}", this.subject.getState());
  12. }
  13. }

3、第二个观察者

  1. package com.asurplus.common.observe;
  2. import lombok.extern.slf4j.Slf4j;
  3. @Slf4j
  4. public class Observer2 extends Observer {
  5. public Observer2(Subject subject) {
  6. this.subject = subject;
  7. this.subject.attach(this);
  8. }
  9. @Override
  10. public void update() {
  11. log.info("观察者 2 收到通知:{}", this.subject.getState());
  12. }
  13. }

4、第三个观察者

  1. package com.asurplus.common.observe;
  2. import lombok.extern.slf4j.Slf4j;
  3. @Slf4j
  4. public class Observer3 extends Observer {
  5. public Observer3(Subject subject) {
  6. this.subject = subject;
  7. this.subject.attach(this);
  8. }
  9. @Override
  10. public void update() {
  11. log.info("观察者 3 收到通知:{}", this.subject.getState());
  12. }
  13. }

5、定义主题

  1. package com.asurplus.common.observe;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /**
  5. * 主题
  6. */
  7. public class Subject {
  8. /**
  9. * 观察者列表
  10. */
  11. private List<Observer> observers = new ArrayList<>();
  12. /**
  13. * 标志
  14. */
  15. private int state;
  16. public int getState() {
  17. return state;
  18. }
  19. /**
  20. * 标识被改变
  21. *
  22. * @param state
  23. */
  24. public void setState(int state) {
  25. this.state = state;
  26. // 通知所有观察者
  27. notifyAllObservers();
  28. }
  29. /**
  30. * 添加进接收者列表
  31. *
  32. * @param observer
  33. */
  34. public void attach(Observer observer) {
  35. observers.add(observer);
  36. }
  37. /**
  38. * 通知所有人被改变
  39. */
  40. public void notifyAllObservers() {
  41. for (Observer observer : observers) {
  42. observer.update();
  43. }
  44. }
  45. }

类似于消息发布一样,有多个接收者,当标志位被改变的时候,通知多个接收者。

二、测试

  1. package com.asurplus.common.observe;
  2. public class TestMain {
  3. public static void main(String[] args) {
  4. // 创建主题
  5. Subject subject = new Subject();
  6. // 添加观察者
  7. new Observer1(subject);
  8. new Observer2(subject);
  9. new Observer3(subject);
  10. // 改变标志
  11. subject.setState(10);
  12. }
  13. }

输出结果

在这里插入图片描述

可以看出,三个接收者都收到了事件通知,从而实现了我们的观察者模式。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注w3xue的更多内容!   

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号