【问题标题】:Why it should be done in such a complicated way? Is it OOP way of thinking?为什么要以如此复杂的方式完成?是面向对象的思维方式吗?
【发布时间】:2010-03-07 17:01:49
【问题描述】:

我正在尝试使用 Java 中的 Bonjour。我找到了一个如何做的例子,我想我理解了。但我仍然不明白为什么要以如此复杂的方式完成。可能是我错过了什么。

所以,code I found 的工作方式如下(代码也在下面给出)。

  1. Java 程序尝试查找服务,如果找到该服务,程序会尝试“解析”该服务(我认为“解析服务”的意思是“使用服务”或“连接到服务”)。

  2. 要“解析”找到的服务,我们需要调用“DNSSD.resolve”方法,并且作为该方法的最后一个参数,我们需要提供一个对象。

  3. “DNSSD.resolve”尝试解析给定的服务。如果“DNSSD.resolve”能够解析服务,它会调用作为最后一个参数给出的实例的“serviceResolved”方法。如果“DNSSD.resolve”无法解析服务,则调用上述对象的“operationFailed”方法。

代码如下:

DNSSD.resolve(0, ifIndex, serviceName, regType, domain, new ResolveListener(){
                public void serviceResolved(DNSSDService resolver, int flags, int ifIndex,
                String fullname, String hostname, int port, TXTRecord txtRecord){
                    InetAddress theAddress;
                    try {
                        theAddress = InetAddress.getByName(hostname);
                    } catch (UnknownHostException e) {
                        // ouch..
                    }
                }

                public void operationFailed(DNSSDService arg0, int arg1) {
                    // ouch, again!
                }
            });

按以下方式组织代码会不会更简单。

  1. 我们调用“DNSSD.resolve”方法,提供有关我们要解析的服务的信息。

  2. 我们不会将任何对象传递给“DNSSD.resolve”。

  3. “DNSSD.resolve”不调用任何类的任何方法。

  4. “DNSSD.resolve”尝试“解析”给定的服务,如果能够做到,“DNSSD.resolve”返回真。否则返回 false。

  5. 程序根据“DNSSD.resolve”返回的值运行“serviceResolved”或“operationFailed”方法。

还是我只是不习惯 OOP 的思维方式?

【问题讨论】:

    标签: java bonjour zeroconf


    【解决方案1】:

    与其说是“OOP 思维方式”,不如说是“异步思维方式”。通过对可能需要一段时间的操作使用回调函数,您可以在等待操作完成时停止做其他事情(或保持 GUI 响应)。

    【讨论】:

    • 但是我应该在什么时候引入这种“并行性”呢?有时程序会调用 DNSSD.resolve,我认为调用程序需要等到 DNSSD 解析服务。
    • 不,DNSSD.resolve() 会立即返回,即使解析尚未完成。您的程序可以返回到处理 GUI 事件或其他任何事情的主循环。解析完成后,您的处理程序对象将在单独的线程中调用,您可以在该线程中处理结果,或者将消息排队返回 GUI 线程以显示结果等。
    【解决方案2】:

    当然,有很多不同的方法可以解决“问题”。这里采用的方法是一种回调方法:您调用 resolve 方法并给它一个方法(嗯,实际上是一个包含方法的对象,因为 Java 没有匿名方法或闭包等......)。 一旦该解析器(未)成功解析了您希望它解析的任何内容,它就会调用您提供给它的 serviceResolved 方法(然后它会处理解析器提供的信息)。

    这意味着它是一种异步方法,但不是 OO。您可以在解析器“工作”时执行其他操作,serviceResolved 方法将在 somewhen 调用,因此您无需等待。

    【讨论】:

    • 你怎么能看到“我可以在解析器工作时做其他事情”?我认为如果我调用一个方法,程序会加权,直到方法完成它的任务,然后程序才会执行方法之后给出的代码。
    • 这样想:方法的工作并不是真正解析服务,只是启动一个线程,以后可以解析服务。所以是的,您的程序必须等待方法完成其任务,但不必等待服务解决。
    【解决方案3】:

    该代码也是 Java -> JNI -> C 代码。没有任何关于它的OO。它是带有 Java 包装器的异步过程代码。

    【讨论】:

    • 你怎么看它是“异步的”?是什么让它“异步”?
    • 您调用代码并告诉它在工作完成时要调用哪些函数,而不是同步等待结果。我查看了这个 Java 包装器调用的 Apple C 代码。
    【解决方案4】:

    DNSSD.resolve 的 JavaDoc 声明“大多数操作是非阻塞的;客户端通过带有操作结果的接口回调。回调由单独的工作线程进行。”

    http://developer.apple.com/mac/library/documentation/Java/Reference/DNSServiceDiscovery_JavaRef/com/apple/dnssd/DNSSD.html

    这就是并行性的来源。

    【讨论】:

      【解决方案5】:

      JBonjourBrowser 中,您可以看到其他人引用的“异步方法”如何在JTree 订阅者模型中使用。作者指出,这“特别有用......设备通常非常短暂,服务会在不久后宣布并消失。

      【讨论】:

        【解决方案6】:

        回调接口样式常用于异步操作。

        在设计一个接口,尤其是涉及网络或IO操作的服务时,经常会出现两个问题: 1. 操作是同步(阻塞)还是异步(非阻塞) 2. 操作是否返回值

        我们不能说回调样式是否是面向对象的。 面向对象的设计是为每个对象分配明确的责任。

        相反,回调机制是OO设计中非常常见的异步操作模式。 1. 负责提供规定服务的服务 2. 负责接收服务响应的回调

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-12-21
          • 1970-01-01
          • 2010-11-15
          • 2011-11-05
          • 1970-01-01
          • 2015-05-20
          • 1970-01-01
          相关资源
          最近更新 更多