【问题标题】:Abstractions should not depend upon details. Details should depend upon abstractions?抽象不应依赖于细节。细节应该取决于抽象吗?
【发布时间】:2010-12-15 03:57:13
【问题描述】:

在过去的几天里,我阅读了很多关于依赖注入/控制反转/依赖反转的内容。我认为,现在我对这个概念的理解要好得多。但我仍然没有从维基百科得到以下信息:

A.高级模块不应该 依赖于低级模块。两个都 应该依赖于抽象。 B. 抽象不应依赖于细节。细节应该 依赖于抽象。

我了解高级模块的部分不应该 依赖于低级模块。但是,我对抽象和细节感到困惑。有人可以为我简化它们。谢谢。

【问题讨论】:

    标签: dependency-injection inversion-of-control


    【解决方案1】:

    这意味着如果细节发生变化,它们不应该影响抽象。抽象是客户查看对象的方式。对象内部究竟发生了什么并不重要。让我们以汽车为例,踏板、方向盘和变速杆是发动机内部发生的事情的抽象。但他们并不依赖于细节,因为如果有人将我的旧引擎换成新引擎,我应该仍然可以在不知道引擎改变的情况下驾驶汽车。

    另一方面,细节必须符合抽象所说的内容。我不想实现一个突然导致刹车使汽车速度加倍的发动机。我可以以任何我想要的方式重新实施刹车,只要它们在外部表现相同。

    【讨论】:

    • 我喜欢 OP 无法理解这个概念 - 非常简洁明了的答案,谢谢。
    • 最佳扩展
    【解决方案2】:

    抽象和细节示例:流提供了读取令牌的接口。这是一个抽象。

    流的流实现必然会实现抽象定义的接口:这就是它依赖它的原因。如果它提供不同的接口(一次读取 100 个字符),它就不能声称实现了相同的抽象。

    【讨论】:

      【解决方案3】:

      想想你需要调用的工作,以及它离你当前编码的地方有多远。那里有一个频谱;您在其上的位置代表了调用该功能所需的工作量。

      抽象使该位置更接近您正在编写的代码。例如,如果您必须调用 Web 服务,您可以 1) 直接在需要使用它的地方编写调用代码,或 2) 将这些细节放在抽象后面(例如接口)。

      在这种情况下,#1 让您更贴近频谱上的 Web 服务,而 #2 让您更贴近您的工作。抽象可以说是衡量你必须在多大程度上扩展你的思想才能理解你需要完成的工作。

      这意味着每一项工作都可以被抽象化,以便它“更接近”使用它的代码。通过让操作的双方都依赖于抽象,它们都变得更容易理解,并且任何一方都不必知道它们之间的差距——这就是抽象的工作。

      哇,太抽象了。

      【讨论】:

        【解决方案4】:

        一个有趣的抽象依赖于细节的例子是当你定义一个继承自IDisposable的接口时。看看下面的抽象:

        public interface ICustomerRepository : IDisposable
        {
            Customer GetById(Guid id);
            Customer[] GetAll();
        }
        

        注意IDisposable 是一个特定于 .NET 的接口,但您可以很容易地想象您的接口包含一个 Dispose 方法本身,而不是从此类接口继承.

        ICustomerRepository 实现IDisposable 可能看起来很方便。通过这种方式,任何调用者都可以处置存储库,而实现也可以通过这种方式处置它在内部使用的连接或工作单元。

        然而,现在编写接口时考虑了某种实现,因为所有ICustomerRepository 实现都需要清理任何资源并不明显。因此,该接口泄露了实现细节,因此违反了依赖倒置原则。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-26
          • 2019-09-22
          相关资源
          最近更新 更多