经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
观察者模式
来源:cnblogs  作者:纳兰小依  时间:2019/9/23 8:54:12  对本文有异议

      观察者模式允许多个观察者订阅一个主题,当主题的状态发生变化时,能够将这种变化通知到每个观察者。从主题的角度看,这是典型的一对多关系,即一个主题可以对应多个观察者。以订阅邮件为例,当订阅某一类主题内容(例如娱乐新闻,动漫等)时,如果该主题的内容有更新,那么每一个订阅该主题的人都会受到一封内容更新的邮件,这便是典型的观察者模式。

      要实现邮件订阅的功能,需要先定义一个主题接口,主题接口需要能够随时添加或者删除订阅人(观察者),并且在有内容更新时通知观察者,其定义如下:

  1. 1 public interface Subject {
  2. 2 //添加观察者
  3. 3 void registerObserver(Observer observer);
  4. 4
  5. 5 //移除观察者
  6. 6 void removeObserver(Observer observer);
  7. 7
  8. 8 //有新内容时通知观察者
  9. 9 void notifyObserver();
  10. 10 }

      与主题接口对应的是观察者接口,接口很简单,在有内容的时候更新状态:

  1. 1 public interface Observer{
  2. 2 void update(); //更新状态
  3. 3 }

      主题接口有许多实现,这里选择娱乐新闻主题作为例子:

  1. 1 import java.util.ArrayList;
  2. 2 import java.util.List;
  3. 3
  4. 4 public class EntertainmentSubject implements Subject{
  5. 5
  6. 6 List<Observer> observerList;
  7. 7
  8. 8 public EntertainmentSubject(){
  9. 9 this.observerList = new ArrayList<>();
  10. 10 }
  11. 11
  12. 12 @Override
  13. 13 public void registerObserver(Observer observer) {
  14. 14 this.observerList.add(observer);
  15. 15 }
  16. 16
  17. 17 @Override
  18. 18 public void removeObserver(Observer observer) {
  19. 19 int i = observerList.indexOf(observer);
  20. 20 if(i >= 0){
  21. 21 observerList.remove(i);
  22. 22 }
  23. 23 }
  24. 24
  25. 25 @Override
  26. 26 public void notifyObserver() {
  27. 27 for(Observer observer : observerList){
  28. 28 observer.update();
  29. 29 }
  30. 30 }
  31. 31
  32. 32 // 假设内容变化时会调用这个接口
  33. 33 public void contentUpdated(){
  34. 34 notifyObserver();
  35. 35 }
  36. 36 }

      主题需要在内容发生变化的时候通知所有的观察者,这里使用contentUpdated()方法来实现,至于主题内容变化如何调用contentUpdated()方法则不在本文的讨论范围内,这里假设只要主题有更新就会调用这个方法。

      接下来定义两个具体的观察者:

  1. 1 public class ConcreteObserver1 implements Observer{
  2. 2
  3. 3 Subject subject;
  4. 4 public ConcreteObserver1(Subject subject) {
  5. 5 this.subject = subject;
  6. 6 }
  7. 7
  8. 8 @Override
  9. 9 public void update() {
  10. 10 System.out.println("ConcreteObserver1, 给你发个邮件,因为这里有新内容了。。。");
  11. 11 }
  12. 12 }
  1. 1 public class ConcreteObserver2 implements Observer{
  2. 2
  3. 3 Subject subject;
  4. 4 public ConcreteObserver2(Subject subject) {
  5. 5 this.subject = subject;
  6. 6 }
  7. 7
  8. 8 @Override
  9. 9 public void update() {
  10. 10 System.out.println("ConcreteObserver2, 给你发个邮件,因为这里有新内容了。。。");
  11. 11 }
  12. 12 }

      好了,所有的类都准备就绪,是时候写个测试来看一下观察者模式的使用了:

  1. 1 public class ObserverTest {
  2. 2 public static void main(String[] args){
  3. 3 EntertainmentSubject subject = new EntertainmentSubject();
  4. 4 ConcreteObserver1 observer1 = new ConcreteObserver1(subject);
  5. 5 ConcreteObserver2 observer2 = new ConcreteObserver2(subject);
  6. 6 subject.registerObserver(observer1);
  7. 7 subject.registerObserver(observer2);
  8. 8 subject.contentUpdated(); //模拟内容更新
  9. 9
  10. 10 subject.removeObserver(observer1); //observer退订
  11. 11 subject.contentUpdated();
  12. 12 }
  13. 13 }

      输出:

  1. ConcreteObserver1, 给你发个邮件,因为这里有新内容了。。。
  2. ConcreteObserver2, 给你发个邮件,因为这里有新内容了。。。
  3. ConcreteObserver2, 给你发个邮件,因为这里有新内容了。。。

      开始的时候有两个观察者,内容更新的时候两个观察者都收到了通知,后来observer1取消了订阅,更新的时候就不再通知这个观察者了。

      当然,这里的观察者模式的逻辑很简单,现实中用到的观察者模式比这要复杂许多,不过底层的结构大体相似。而且,Java也提供了观察者模式的相关实现Observable和Observer,使用的时候需要将Subject换成Observable,需要注意的是Observable是类而不是接口,所以如果你的类已经继承了其他类,就无法使用Java的这套API了。

参考:

<<Head First设计模式>>

原文链接:http://www.cnblogs.com/NaLanZiYi-LinEr/p/11565703.html

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

本站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号