• Java核心篇,二十三种设计模式(十九),行为型——观察者模式


    一、概念

    它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己

    二、适用场景

    • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。 将这二者封装在独立的对象中以使它
    • 们可以各自独立地改变和复用
    • 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改
    • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁

    三、成员角色

    • 抽象主题(Subject)角色:也叫抽象目标类;用于注册、移除、通知观察者;它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法
    • 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的方法;当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。继承 Subject 类,在这里实现具体业务,在具体项目中,该类会有很多变种。
    • 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用
    • 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态

    四、优缺点

    优点

    • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则
    • 目标与观察者之间建立了一套触发机制

    缺点

    • 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用
    • 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率

    五、业务分析

    我们每个人都在使用微信,微信中有两种角色,一种是微信公众号,一种是普通用户;普通用户可以关注微信公众号;如果微信公众号发布了新文章,那么关注他的用户将会收到通知;这就是最常见的观察者模式

     

    六、代码实现

    Subject

    1. package com.designer.observe.Subject;
    2. import com.designer.observe.Observer.Observer;
    3. /**
    4. * 抽象主题(Subject)角色
    5. * 用来模拟微信公众号抽象模板
    6. */
    7. public interface Subject {
    8. void registerObserver(Observer o);
    9. //移除监听器
    10. void removeObserver(Observer o);
    11. //发送消息
    12. void notifyObservers();
    13. }

    ConcreteSubject

    1. package com.designer.observe.ConcreteSubject;
    2. import com.designer.observe.News;
    3. import com.designer.observe.Observer.Observer;
    4. import com.designer.observe.Subject.Subject;
    5. import java.util.ArrayList;
    6. import java.util.List;
    7. /**
    8. * 具体主题(Concrete Subject)角色
    9. * 用来模拟微信公众号
    10. */
    11. public class ConcreteSubject implements Subject {
    12. private List<Observer> observers;
    13. private News news;
    14. public ConcreteSubject(){
    15. this.observers = new ArrayList<>();
    16. }
    17. public void setNews(News news) {
    18. this.news = news;
    19. }
    20. @Override
    21. public void registerObserver(Observer o) {
    22. this.observers.add(o);
    23. }
    24. @Override
    25. public void removeObserver(Observer o) {
    26. this.observers.remove(o);
    27. }
    28. @Override
    29. public void notifyObservers() {
    30. for (Observer observer: this.observers) {
    31. observer.update(this.news);
    32. }
    33. }
    34. }

    Observer

    1. package com.designer.observe.Observer;
    2. import com.designer.observe.News;
    3. /**
    4. * 抽象观察者(Observer)角色
    5. * 用来模拟 关注微信公众号的粉丝 模板
    6. */
    7. public interface Observer {
    8. void update(News news);
    9. }

    ConcreteObserver

    1. package com.designer.observe.ConcreteObserver;
    2. import com.designer.observe.News;
    3. import com.designer.observe.Observer.Observer;
    4. /**
    5. * 具体主题(Concrete Subject)角色
    6. * 用来模拟 微信公众号的具体粉丝
    7. */
    8. public class ConcreteObserver implements Observer {
    9. private String name;
    10. private News news;
    11. public ConcreteObserver(String name){
    12. this.name = name;
    13. }
    14. @Override
    15. public void update(News news) {
    16. this.news = news;
    17. showNews();
    18. }
    19. private void showNews(){
    20. System.out.println("尊敬的" + this.name + ",您订阅的 " + this.news.getAuthor() + " 刚刚发布了" + this.news.getTitle() + " 内容如下:");
    21. System.out.println(this.news.getContext());
    22. System.out.println();
    23. }
    24. }

    News

    1. package com.designer.observe;
    2. /**
    3. * 新闻类
    4. */
    5. public class News {
    6. private String author;
    7. private String title;
    8. private String context;
    9. public News(String author, String title, String context) {
    10. this.author = author;
    11. this.title = title;
    12. this.context = context;
    13. }
    14. public String getAuthor() {
    15. return this.author;
    16. }
    17. public String getTitle() {
    18. return this.title;
    19. }
    20. public String getContext() {
    21. return this.context;
    22. }
    23. }

    Test

    1. package com.designer.observe;
    2. import com.designer.observe.ConcreteObserver.ConcreteObserver;
    3. import com.designer.observe.ConcreteSubject.ConcreteSubject;
    4. public class Test {
    5. public static void main(String[] args) {
    6. // 微信公众号
    7. ConcreteSubject subject = new ConcreteSubject();
    8. // 粉丝
    9. ConcreteObserver observer1 = new ConcreteObserver("粉丝1");
    10. ConcreteObserver observer2 = new ConcreteObserver("粉丝2");
    11. ConcreteObserver observer3 = new ConcreteObserver("粉丝3");
    12. // 粉丝关注微信公众号
    13. subject.registerObserver(observer1);
    14. subject.registerObserver(observer2);
    15. subject.registerObserver(observer3);
    16. // 粉丝取消关注微信公众号
    17. subject.removeObserver(observer2);
    18. // 微信公众号发布文章
    19. News news = new News("IT蓝月", "美国宣布对华取消关税!", "2022年x月x日,美国最终因为通货膨胀的压力,宣布对华取消了关税。");
    20. subject.setNews(news);
    21. // 推送给粉丝
    22. subject.notifyObservers();
    23. }
    24. }

  • 相关阅读:
    (复刷) 面试题02.07.链表相交
    django的cookie和session
    倒计时列表实现(小程序端&Vue)
    EtherCAT主站转Ethernet/IP网关
    C++协程
    沈阳建筑大学《乡村振兴战略下传统村落文化旅游设计》 许少辉八一著作
    华为mate60麒麟9000s的架构体系
    rsync下行同步+inotify实时同步部署
    面向对象进阶
    WPF快速学习入门(9.依赖属性)
  • 原文地址:https://blog.csdn.net/ITlanyue/article/details/125450496