1

作为面向对象的程序员,我遇到了一些遗留代码,这些代码引起了我的所有质问。

这是经常使用的模式: 一个接口有两个实现,一个实现调用另一个实现的方法。

现在,我认为应该对其进行重构,以便实现彼此不了解。如何做到这一点很简单。我无法清楚地弄清楚 - 并希望 SO 的好人能帮助我 - 是为什么。

我可以看到理论上的原因——这是一个糟糕的面向对象设计。但是我在这里扮演魔鬼的拥护者并问 - 两个实现相互了解的实际缺点是什么。为什么要花费时间和金钱来摆脱这种(在我看来)反模式?

任何有关此的信息或链接将不胜感激。

4

4 回答 4

2

我可以看到理论上的原因——这是一个糟糕的面向对象设计。

为什么?这对我来说听起来完全合理。

例如,假设我想装饰每个调用 - 例如添加调用频率的统计信息,或添加一些授权检查等。将装饰与实际实现分开是有意义的,只需委托:

public class DecoratedFoo : IFoo
{
    private readonly IFoo original;

    public DecoratedFoo(IFoo original)
    {
        this.original = original;
    } 

    public string Bar() // Defined in IFoo
    {
        // Update statistics here, or whatever
        return original.Bar();
    }
}

为什么您认为关注点分离是“非常面向对象的设计”?即使装饰类知道特定实现IFoo调用不属于IFoo自身的成员以提高效率,对我来说似乎并不特别糟糕。这只是一个类知道另一个类,它们碰巧实现了相同的接口。它们比上面知道的例子更紧密地耦合IFoo,但它仍然不是“可怕的”。

于 2012-05-07T19:21:18.827 回答
1

interface1 的 implementation1 知道 interface1 的 implementation2 或与 interface1 的 implementation2 交互没有任何问题。

我认为您刚刚发现了代理模式的预期或非预期实现 http://en.wikipedia.org/wiki/Proxy_pattern

希望这可以帮助 :)

于 2012-05-08T11:25:07.310 回答
0

第一个实现调用的“其他实现”的方法就是我所说的库函数。将它放在一个单独的模块/文件/项目/任何东西中(取决于您的语言/开发环境),并让两个实现都包含它并从那里使用它。

包含公共代码的某些接口的两个实现绝对没有错,但是当然,公共代码可能应该与每个实现分开,这样您就可以将其中一个加载到您的程序中而不必加载另一个。

于 2012-05-07T19:19:52.810 回答
0

我对此的想法是

  1. 假设在适当的时候,如果您要停用一个实现并且将其单独保留,那么另一个实现没有变化,您不需要对其进行测试。如果没有分离,您需要花时间分离和测试其他实现。

  2. 承担单一责任总是更清洁。

于 2012-05-07T19:22:08.530 回答