浅谈Observer在代码中表现形式

Posted 饭小胖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈Observer在代码中表现形式相关的知识,希望对你有一定的参考价值。

  说到观察者模式,基本在软件工程领域中是应用广泛,不知道的可以先学习一番,下面给个快速的回顾,然后在通过一个grpc中的responseObserver谈下观察者对象在代码中的位置。

  喜欢类图,就不上其他图了,只有能看懂类图,才好说吗观察者在代码中的位置。但也要总结下观察者的消息事件对象:

  1、观察者订阅某个主题;

  2、主题发生变化,然后通知观察者

  3、观察着收到通知,然后作出响应

  这里涉及两类对象,观察者和被观察者(主题),首先第一步,观察者订阅某个主题,在业务领域,该行为动作应该由观察者自身发起的,但别扭的是,如上类图,注册这件事是由主题发起的,其实这样真的误导很多人,我们看Redis的发布订阅模式,其实类似观察者模式,但订阅这件事是由观察者发起的;

redis 127.0.0.1:6379> SUBSCRIBE redisChat

Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1

  如果按照DDD的思想,这类代码的编写其实要非常注重,因为和领域逻辑偏离一点,扯出来的维护工作可能就很大。

  那我们需要在观察者中加入注册/订阅这类代码吗?当然是不好的,因为一般注册这件事,在抽象程度上,不应该划分到任何一个类中,所以我们通常利用IOC思想,在第三方中做注册和订阅这件事,比喻下面的main方法类(你可以做成领域服务类);

  

public class Test {
    
    public static void main(String[] args) {
        WechatServer server = new WechatServer();
        
        Observer userZhang = new User("ZhangSan");
        Observer userLi = new User("LiSi");
        Observer userWang = new User("WangWu");
        
        server.registerObserver(userZhang);
        server.registerObserver(userLi);
        server.registerObserver(userWang);
        server.setInfomation("php是世界上最好用的语言!");
        
        System.out.println("----------------------------------------------");
        server.removeObserver(userZhang);
        server.setInfomation("JAVA是世界上最好用的语言!");
        
    }
}

  可以看到,观察者之所以在“观察”,是因为由个第三方帮它订阅了事件;下面我们看第三个例子,这个例子是我在grpc中看到的,如下:

  

    @Override
    public void getFeature(Point request, StreamObserver<Feature> responseObserver) {
      responseObserver.onNext(checkFeature(request));
      responseObserver.onCompleted();
    }

...

    private Feature checkFeature(Point location) {
      for (Feature feature : features) {
        if (feature.getLocation().getLatitude() == location.getLatitude()
            && feature.getLocation().getLongitude() == location.getLongitude()) {
          return feature;
        }
      }

      // No feature was found, return an unnamed feature.
      return Feature.newBuilder().setName("").setLocation(location).build();
    }

  注意getFeature中的一个参数,称之为:responseObsever,他们叫,应答观察者,意思是,如果该远程调用的服务端做了什么事,请通知应答观察者对象,因为它需要做相应的行为,包括返回调用的结果;我们首先要知道,针对每一次RPC,该对象都是独一无二的,存在多个这样的对象,他们观察着各种感兴趣的事情(也就是我只实现了这些事件的应答,其他事情我不会谢谢),而这个时候,该对象的引用就在主题的代码中明显的完成这件事的操作;可见,如果你从代码中看待观察者是真的会乱七八糟的;

  从此可以看出,其实代码只是实现的方式,和实际的内存模型是有差别的;因此,各种设计模式都不能在代码和类图中学习,而是实际的把它们当作实体和对象;

  例如对于方法调用,代码看是写的混在一起,其实只是一种让计算机读懂的东西而已,在内存中的对象模型;其实方法调用,根本就是消息传递;指示者程序计数器的转动而已。

  例如,状态模式和策略模式,它们类图都非常相似,可是实质差别却非常大。

  最后总结一下:不要在代码中思考,任何设计,请把思维提高一层,用实体对象对待它们,代码只是计算机要读懂你的思维而已。

 

以上是关于浅谈Observer在代码中表现形式的主要内容,如果未能解决你的问题,请参考以下文章

为啥相同的 MySql 查询在代码和工作台中表现不同?

编译 C++ 代码以在 Windows 和 Linux 中表现相同 [关闭]

NHibernate总结

腾讯TMQ浅谈Chromium中的设计模式(终)——Observer模式

为啥 Rust RwLock 在 fork 中表现异常?

QHash 在不同的 qt 版本中表现不同