【设计模式】观察者模式

观察者模式

  • 观察者模式的定义
    • 定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于他的对象都会得到通知并被自动更新
  • 在这里插入图片描述
    • Subject:目标对象,通常具有如下功能
      • 一个目标可以被多个观察者观察
      • 目标提供对观察者注册和退订的维护
      • 当目标的状态发生变化时,目标负责通知所有注册的、有效的观察者
    • Observer:定义观察者的接口,提供目标通知时对应的更新方法,这个更新方法进行相应的业务处理,可以在这个方法里面回调目标对象,以获取目标对象的数据
    • ConcreteSubject:具体的目标实现对象,用来维护目标状态,当目标对象的状态发生改变时,通知所有注册的、有效的观察者,让观察者执行相应的处理
    • ConcreteObserver:观察者的具体实现对象,用来接收目标的通知,并进行相应的后续处理,比如更新自身的状态以保持和目标的相应状态一致
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Observer;
      
      /*
      * 目标对象,它知道观察它的观察者,并提供注册和删除观察者的接口
      * */
      public class Subject {
          /*
          * 用来保存注册的观察者对象
          * */
          private List<Observer> observerList = new ArrayList<Observer>();
          /*
          * 注册观察者对象
          * @param observer 观察者对象
          * */
          public void attach(Observer observer) {
              observerList.add(observer);
          }
      
          /*
          * 删除观察者对象
          * @param observer 观察者对象
          * */
          public void detach(Observer observer) {
              observerList.remove(observer);
          }
          /*
          * 通知所有注册的观察者对象
          * */
          public void notifyObservers() {
              for (Observer observer : observerList) {
                  observer.update(this);
              }
          }
      }
      
      /*
      * 具体的目标对象,负责把有关状态存入到相应的观察者对象
      * 并在自己状态发生改变时,通知各个观察者
      * */
      public class ConcreteSubject extends Subject {
          /*
          * 示意,目标对象的状态
          * */
          private String subjectState;
          public String getSubjectState() {
              return subjectState;
          }
          public void setSubjectState(String subjectState) {
              this.subjectState = subjectState;
              /*
              * 状态发生了改变,通知各个观察者
              * */
              this.notifyObservers();
          }
      }
      
      /*
      * 观察者接口,定义一个更新的接口给那些在目标发生改变的时候被通知的对象
      * */
      public interface Observer {
          /**
           * 更新的接口
           * @param subject 传入目标对象,方便获取相应的目标对象的状态
           */
          public void update(Subject subject);
      }
      
      /**
       * 具体观察者对象,实现更新的方法,使自身的状态和目标的状态保持一致
      */
      public class ConcreteObserver implements Observer {
          /**
           * 示意,观察者模式
           */
          private String observerState;
      
          public void update(Subject subject) {
              // 具体的更新实现
              // 这里可能需要更新观察者的状态,使其与目标的状态保持一致
              observerState = ((ConcreteSubject) subject).getSubjectState();
          }
      }
      
  • 目标和观察者之间的关系:一对多
  • 单向依赖:在观察者模式中,观察者和目标是单向依赖的,只有观察者依赖于目标,而目标是不会依赖于观察者的
  • 基本的实现说明
    • 具体的目标实现对象要能维护观察者的注册信息,最简单的实现方案就如同前面的例子那样,采用一个集合来保存观察者的注册信息
    • 具体的目标实现对象需要维护引起通知的状态,一般情况下是目标自身的状态。变形使用的情况下,也可以是别的对象的状态
    • 具体的观察者实现对象需要能接受目标的通知,能够接收目标传递的数据,或者是能够主动去获取目标的数据,并进行后续处理
    • 如果是一个观察者观察多个目标,那么在观察者的更新方法里面,需要去判断是来自哪一个目标的通知。一种简单的解决方案就是扩展update方法,比如在方法里面多传递一个参数进行区分等;还有一个更简单的方法,那就是干脆定义不同的回调方法
  • 在观察者模式的实现中,又分为推模式和拉模式两种模式
    • 推模式
      • 目标对象主动向观察者推送目标的详细信息,不管观察者是否需要,推送的信息通常是目标对象的全部或部分数据,相当于是在广播通信
    • 拉模型
      • 目标对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据。一般这种模型的实现中,会把目标对象自身通过update的方法传递给观察者,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了
    • 关于两种模型的比较
      • 推模型是假定目标对象知道观察者需要的数据;而拉模型是目标对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传给观察者,让观察者自己按需取值
      • 推模型可能使得观察者对象难以服用,因为观察者定义的update方法是按需而定义的,可能无法兼顾没有考虑到的使用情况。这就意味着出现新的情况的时候,就可能需要提供新的update方法,或者是干脆重新实现观察者
  • 观察者模式的优缺点
    • 优点
      • 观察者模式实现了观察者和目标之间的抽象耦合
      • 观察者模式实现了动态联动
      • 观察者模式支持广播通信
    • 缺点
      • 可能会引起无谓的操作
  • 观察者模式的本质
    • 触发联动
  • 何时选用观察者模式
    • 当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化,那么就可以选用观察者模式,将这两者封装成观察者和目标对象,当目标对象变化的时候,依赖于它的观察者对象也会发生相应的变化。这样就可以把抽象模型的这两个方面分离开了,使得它们可以独立地改变和复用
    • 如果在更改一个对象的时候,需要同时连带改变其他的对象,而且不知道究竟应该有多少对象需要被连带改变,这种情况可以选用观察者模式,被更改的那一个对象很明显就相当于是目标对象,而需要连带修改的多个其他对象,就作为多个观察者对象了
    • 当一个对象必须通知其他的对象,但是你又希望这个对象和其他被通知的对象是松散耦合的。也就是说这个对象其实不想知道具体被通知的对象。这种情况可以选用观察者模式,这个对象就相当于是目标对象,而被他通知的对象就是观察者对象了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值