10、观察者模式

1、观察者模式介绍

观察者定义了一种一对多的依赖关系,当一个主题(Subject)对象状态发生变化时,所有依赖它的相关对象都会得到通知并且能够自动更新自己的状态,这些依赖的对象称之为观察者(Observer)对象这类似于发布/订阅模式。

观察者模式中的主题对象,会维持着一个依赖它的观察者对象列表,当主题对象状态发生改变时,主题对象便会调用这个列表中所有观察者对象的方法。

观察者模式一般用在分布式时间处理系统,它也是流行的MVC模型的核心设计模式。

在程序中,很多时候,我们需要等待另一方的一个状态来决定如何进行下一步,这个时候就需要不断的循环去查看对方的状态,不断轮询对CPU资源的占用是非常的大的,而且是空跑,做无用功。

观察者模式就是为了解决这样子的问题而产生的。他不是不断轮询对方状态,而是把自己作为观察者,注册到对方的对象中,这样,对方状态改变时,直接调用自己的触发方法(update)进行工作即可,从而较少了自己不断轮询带来的性能消耗。

其中比较经典的就是Java的swing,比如要等到button click事件发生,然后去做一件事情,只需要给这个button对象注册一个观察者(listener),当button对象的click发生时,调用listener的对应方法去处理相应逻辑。

以上的这种做法,只能够在单机版程序中,对象大家都在同一个jvm堆内存中,可以将引用交给对方,但是如果在分布式程序中,不同的组件运行在不同的机器集群。

2、代码示例

  • 1、被订阅号

      import java.util.Observable;
    
      /**
       * [@Author](https://my.oschina.net/arthor) liufu
       * @CreateTime 2018/3/28  17:37
       */
      public class ServiceProvider extends Observable {
          int offset = 0;
    
          private String data;
    
          public String getData() {
              return data;
          }
    
          public void setData(String data) {
              offset++;
              if (this.data != data){
                  System.out.println(data);
                  this.data = data;
    
                  //这两个必须组合使用,否则无效
                  //notifyObservers不要求传递参数,参数会传递给订阅者的update方法
                  setChanged();
                  notifyObservers(offset);
    
              }
              this.data = data;
          }
      }
    
  • 2、观察者1

      import java.util.Observable;
      import java.util.Observer;
    
      /**
       * [@Author](https://my.oschina.net/arthor) liufu
       * @CreateTime 2018/3/28  17:46
       */
      public class Observer1 implements Observer {
    
          /**
           * 创建对象的时候,订阅某个主题
           * [@param](https://my.oschina.net/u/2303379) sp
           */
          public Observer1(ServiceProvider sp){
              sp.addObserver(this);
          }
    
          /**
           * 被订阅的对象发生变化了,这里要做相应的处理
           * @param o
           * @param arg
           */
          @Override
          public void update(Observable o, Object arg) {
              ServiceProvider provider = (ServiceProvider) o;
              System.out.println("Observer1: 我收到了,你想说的是:{" + provider.getData() + "}, offset: " + arg.toString());
          }
      }
    
  • 3、观察者2

      import java.util.Observable;
      import java.util.Observer;
    
      /**
       * @Author liufu
       * @CreateTime 2018/3/28  17:46
       */
      public class Observer2 implements Observer {
    
          /**
           * 创建对象的时候,订阅某个主题
           * @param sp
           */
          public Observer2(ServiceProvider sp){
              sp.addObserver(this);
          }
    
          /**
           * 被订阅的对象发生变化了,这里要做相应的处理
           * @param o
           * @param arg
           */
          @Override
          public void update(Observable o, Object arg) {
              //这里阻塞了,导致1和3都要等待,说明ServiceProvider回调的时候不是开线程处理
              try {
                  Thread.sleep(10000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              ServiceProvider provider = (ServiceProvider) o;
              System.out.println("Observer2: 我收到了,你想说的是:{" + provider.getData() + "}, offset: " + arg.toString());
          }
      }
    
  • 4、观察者3

      import java.util.Observable;
      import java.util.Observer;
    
      /**
       * @Author liufu
       * @CreateTime 2018/3/28  17:46
       */
      public class Observer3 implements Observer {
    
          /**
           * 创建对象的时候,订阅某个主题
           * @param sp
           */
          public Observer3(ServiceProvider sp){
              sp.addObserver(this);
          }
    
          /**
           * 被订阅的对象发生变化了,这里要做相应的处理
           * @param o
           * @param arg
           */
          @Override
          public void update(Observable o, Object arg) {
              ServiceProvider provider = (ServiceProvider) o;
              System.out.println("Observer3: 我收到了,你想说的是:{" + provider.getData() + "}, offset: " + arg.toString());
          }
      }
    
  • 5、测试调度类

      public class ObServerTest {
          public static void main(String[] args) {
              //先创建订阅号
              ServiceProvider serviceProvider = new ServiceProvider();
    
              //执行的顺序是2 --> 1 --> 3
              Observer1 observer1 = new Observer1(serviceProvider);
              Observer2 observer2 = new Observer2(serviceProvider);
              Observer3 observer3 = new Observer3(serviceProvider);
    
              serviceProvider.setData("亲爱们,我变美了,你知道吗!");
              serviceProvider.setData("亲爱们,我you变美了,你知道吗!");
          }
      }
    

转载于:https://my.oschina.net/liufukin/blog/2222543

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值