厚积薄发打卡Day45: [itcast] GoF23通俗易懂的设计模式之 <观察者模式>

前言:

视频教程:黑马程序员Java设计模式详解,全网最全23种Java设计模式

什么是设计模式?

  • 设计模式(Design Pattern)是前辈们对代码开发经验的总结,是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。
  • 1995年,GoF(Gang of Four,四人组)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了23种设计模式,人称 【GoF设计模式】
设计模式分类 具体模式
创建型模式:
它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。
⌛单例模式、⌛工厂模式、⌛抽象工厂模式、⌛建造者模式、⌛原型模式
结构型模式:
结构型模式描述如何将类或对象按某种布局组成更大的结构。
⌛适配器模式、⌛桥接模式、⌛装饰模式、⌛代理模式、⌛外观模式、⌛组合模式、⌛享元模式、
行为型模式:
这些设计模式特别关注对象之间的通信。
⌛模板方法模、⌛策略模式、⌛命令模式、⌛职责链模式、⌛状态模式、⌛观察者模式、迭代器模式、中介者模式、备忘录模式、解释器模式、访问者模式

观察者模式:

观察者模式:

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

概述:

  • 定义

    观察者模式又称:发布-订阅(Publish/Subscribe)模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

  • 结构

    厚积薄发打卡Day45: [itcast] GoF23通俗易懂的设计模式之 <观察者模式>_第1张图片

    在观察者模式中有如下角色:

    • Subject:抽象主题(抽象被观察者):

      抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。

    • ConcreteSubject:

      具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。

    • Observer:

      抽象观察者,是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。

    • ConcrereObserver:

      具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

实例:

【微信公众号】

既然观察者模式都叫发布-订阅(Publish/Subscribe)模式,那如果不写个订阅发布的例子,岂不是很不搭?在微信公众号的是用过程中:公众号发布文章,将会将文章推送给订阅公众号的用户手中,用户们将会收到公众号更新的通知。

在这个例子中:

  • 微信公众号:被观察者,也就是发布者。其中的具体公众号就是具体的主题类。
  • 微信用户:观察者:也就是订阅者。其中具体的微信用户就是具体观察者。

上代码:

厚积薄发打卡Day45: [itcast] GoF23通俗易懂的设计模式之 <观察者模式>_第2张图片

  • 抽象观察者类:

    //微信用户,能收到来自公众号的信息
    public interface Observer {
        void receive(String message);
    }
    
  • 具体观察者:

    //微信订阅用户
    public class WeixinUser implements Observer {
        //微信用户名:
        private String name;
    
        public WeixinUser(String name) {
            this.name = name;
        }
    
        @Override
        public void receive(String message) {
            System.out.println(name +"-"+message);
        }
    }
    
  • 抽象被观察者:

    //抽象主题类:即微信公众号
    public interface Subject {
        //增加订阅者:
        public void attach(Observer observer);
        //删除订阅者:
        public void detach(Observer observer);
        //通知订阅者更新信息:
        public void notify(String message);
    }
    
  • 具体的被观察者:

    //具体的一个微信公众号运营
    public class SubscriptionSubject implements Subject {
        //储存订阅公众号的用户
        private List<Observer> weixinUserList = new ArrayList<Observer>();
    
        @Override
        public void attach(Observer observer) {
            weixinUserList.add(observer);
        }
    
        @Override
        public void detach(Observer observer) {
            weixinUserList.remove(observer);
        }
    
        @Override
        public void notify(String message) {
            for (Observer observer : weixinUserList) {
                observer.receive(message);
            }
        }
    }
    
  • 运行结果:

    厚积薄发打卡Day45: [itcast] GoF23通俗易懂的设计模式之 <观察者模式>_第3张图片

小结:

优缺点

  • 优点:

    • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
      • 也就是在类中实现对象耦合。
    • 被观察者发送通知,所有注册的观察者都会收到信息【可以实现广播机制】
  • 缺点:

    • 如果观察者非常多的话,那么所有的观察者收到被观察者发送的通知会耗时
    • 如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,会导致系统崩溃

使用场景

  • 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时。

应用案例:

  1. JDK中的应用:

    在 Java 中,通过 java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例。

    1,Observable类

    厚积薄发打卡Day45: [itcast] GoF23通俗易懂的设计模式之 <观察者模式>_第4张图片

    • 值得注意的时,void notifyObservers(Object arg) 方法:通常越晚加入集合的观察者越先得到通知:深入查看源码得知时倒序通知。

      厚积薄发打卡Day45: [itcast] GoF23通俗易懂的设计模式之 <观察者模式>_第5张图片

    2,Observer 接口

    Observer 接口是抽象观察者,它监视目标对象的变化,当目标对象发生变化时,观察者得到通知,并调用 update 方法,进行相应的工作。

    public interface Observer {
        void update(Observable o, Object arg);
    }
    

    3,举例应用:

    【例】警察抓小偷

    警察抓小偷也可以使用观察者模式来实现,警察是观察者,小偷是被观察者。

    • 警察:

      public class Police implements Observer {
          private String name;
      
          public Police(String name) {
              this.name = name;
          }
          public void setName(String name) {
              this.name = name;
          }
      
          public String getName() {
              return name;
          }
      
          @Override
          public void update(Observable o, Object arg) {
              System.out.println("警察:" + ((Thief) o).getName() + ",我已经盯你很久了,你可以保持沉默,但你所说的将成为呈堂证供!");
          }
      }
      
    • 小偷:

      public class Thief extends Observable {
          //小偷名字
          private String name;
      
          public Thief(String name) {
              this.name = name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public String getName() {
              return name;
          }
      
          public void steal() {
              System.out.println("小偷:渣渣们,老子来偷东西了!");
              super.setChanged(); //changed  = true
              super.notifyObservers();
          }
      }
      
    • 警察抓小偷:

      厚积薄发打卡Day45: [itcast] GoF23通俗易懂的设计模式之 <观察者模式>_第6张图片

  2. Spring中的应用:

    1. Spring之事件监听(观察者模型)【波波烤鸭.著】

      1. Spring中事件监听的结构

      2. 总结:

        1. Spring中的事件监听使用的是观察者模式
        2. 所有事件需要继承ApplicationEvent父类
      3. 所有的监听器需要实现ApplicationListener接口
        4. 事件发布需要通过ApplicationContext中的publisherEvent方法实现
        5. 监听器的注册是ApplicationEventMulticaster提供的,但我们并不需要实现。

      4. 扩展:

        1. 三种方式实现观察者模式 及 Spring中的事件编程模型
        2. Spring 应用之观察者设计模式
  3. Servlet中的Listener

    实例解析观察者模式及其在Java设计模式开发中的运用

    在说Servlet中的Listener之前,

    先说说观察者模式的另一种形态——事件驱动模型。与上面提到的观察者模式的主题角色一样, 事件驱动模型包括事件源, 具体事件, 监听器, 具体监听器。
    Servlet中的Listener就是典型的事件驱动模型。

    厚积薄发打卡Day45: [itcast] GoF23通俗易懂的设计模式之 <观察者模式>_第7张图片

你可能感兴趣的:(黑马学习,Java基础进阶,设计模式,设计模式,java,spring)