【问题标题】:Liskov Substitution Principle (LSP), Proxy Pattern and ExceptionsLiskov 替换原则 (LSP)、代理模式和异常
【发布时间】:2015-02-13 10:32:37
【问题描述】:

假设我有客户端代码使用的接口和具体实现。现在,使用实现该接口的代理模式,我可以通过网络将发出的请求路由到该接口。网络连接当然会失败,这可能会引发异常。

然后,使用该接口的客户端代码会出现意外异常。我猜在这种情况下违反了 LSP 原则。

但是如果不允许网络异常传播到接口之外,在这种情况下如何处理网络异常?

这里有一些 Java 代码来阐明我的意思:

interface Interface
{
    abstract void method1();
    abstract void method2();
    abstract void method3();
}

class Implementation implements Interface
{
    void method1();
    void method2();
    void method3();
}

class ProxyOverNetwork implements Interface
{
    // I can't add the NetworkException as it is not part of the Interface 
    // and would violate LSP, but how to handle the network problems then,
    // when the ProxyOverNetwork might not be the right place to do so?

    void method1() throws(NetworkException);
    void method2() throws(NetworkException);
    void method3() throws(NetworkException);
}

我是否必须更改接口以允许异常传播出去?

【问题讨论】:

  • 为什么你认为连接失败违反了里氏替换原则?问问自己我们在这里有多少责任?
  • 原始接口与网络访问没有任何关系,因此也不会指定抛出任何异常,但使用网络的代理实现会。
  • 我认为代理(在幕后)用作依赖项的分发机制在这里让您感到困惑。您可以尝试将其抽象为代理接口的依赖项,然后事情会更清楚。

标签: design-patterns exception-handling liskov-substitution-principle


【解决方案1】:

鉴于您使用 Java 编写,如果您希望以一种方法调用可能失败的方式实现您的 Interface,您需要做以下两件事之一:要么

  • 更改Interface 的方法,以便它们引发检查异常,或者
  • 使实现引发未经检查的异常。

在 SO 和整个 Internet 上详细讨论了已检查和未检查异常的相对优缺点。几年来我没有写太多 Java,但几年前的趋势是只使用未经检查的异常,以省去调用者处理它们的麻烦。诚实的 Ruby 人(我就是其中之一)会告诉你,由于他们的无类型语言,他们总是忘记处理错误情况,并最终在修补程序中处理它们。 Haskell 现在很流行,这是一种使用类型签名来限制行为的语言,这种语言会让 unchecked-exceptions 阵营尖叫着跑到山上。

我会使用检查异常来确保调用者处理可能的故障。不过,我不会使用NetworkException,而是像MethodFailureException 这样的通用名称(如果我们知道Interface 我们可以选择更好的名称)NetworkException 可以扩展。这使调用者无需了解实现,同时仍允许他们处理错误。

【讨论】:

    猜你喜欢
    • 2015-09-18
    • 2013-08-23
    • 1970-01-01
    • 1970-01-01
    • 2013-12-15
    • 2014-06-05
    • 2010-12-03
    • 2017-10-18
    • 2019-10-29
    相关资源
    最近更新 更多