接口继承是一种不好的做法吗?

时间:2011-08-09 14:20:19

标签: c# oop design-patterns inheritance

我想知道下面的代码是否显示了一个不好的做法(关于接口继承):

public interface IFoo : IDisposable
{
    void Test();
}

public class TestImpl : IFoo
{
    public void Test()
    {
        // do something
    }

    public void Dispose()
    {
        // disposing my dependencies
    }
}

public class FooFactory
{
    public IFoo CreateFoo()
    {
        return new TestImpl();
    }
}

public class Client
{
    public void Main()
    {
        FooFactory factory = new FooFactory();
        using(IFoo foo = factory.CreateFoo())
        {
            // do stuff then auto-dispose
            foo.Test();
        }
    }
}

在这里,我想要两件事: 1.使用C#的using语句,这样我就可以优雅地处理我的具体对象的依赖项(不需要向IDisposable投射任何东西)。 2.使用工厂方法创建具体对象,因此我只能使用接口。

分开,两者都是已知的良好做法,但在一起?我在http://msdn.microsoft.com/en-us/library/ms229022.aspx(MSDN - 接口设计)找不到任何说错的东西,但我认为听起来不错......

我将不胜感激任何评论。如果这是一个不好的做法,我会遇到什么样的问题?

谢谢!

4 个答案:

答案 0 :(得分:17)

在野外,没有绝对好或坏的做法,每个都有其优点和缺点。
只有当应用于具体问题时,练习才会变得好或坏(读作:不是IFoo)。

public bool IsGood<TContext>(IPractice practice)
    where TContext : RealWorldApplication, new();

因此,不要试图在MSDN上找到指导,而是问自己以下问题:

  

这是否解决了问题使代码更容易阅读?

如果答案是,请使用它。

就个人而言,我喜欢这种方法。如果IFoo 的合同需要正确处理(请注意:IGraphicalObjectIResourceIConnection),那么这是一个非常好的设计决策明确的。

不要被教条困住:使用接口编程可以减少对具体实现的依赖,但使用接口编程 可能是一场噩梦。合理,就是这样。

更新

您可以使用Google查找从.NET Framework本身的IDisposable继承的所有接口:

  

intitle:interface "inherits idisposable" site:msdn.microsoft.com

正如我上面所说,这通常是为已知以消耗资源的实体完成的,例如数据库连接,非托管对象包装器,图形对象等等。

无处理的类强制执行Dispose()将是一个坏主意。
在这种情况下,最好将其保留为可选项并检查IDisposable支持,为suggested by Peter

答案 1 :(得分:10)

这完全有效。这正是接口的用途。他们定义合同。可以使用多个子合同构建合同。

答案 2 :(得分:3)

我认为这是正确的。您的工厂隐藏了实际实例化的类,因此IFoo必须继承IDisposable,以便客户端能够调用Dispose()。通过这个类,客户端可以 - 而且应该 - 完全不知道实例化的实例类。所有相关信息都应由界面携带 - 包括处置的必要性。

答案 3 :(得分:2)

从技术上讲,这个解决方案一切都很好。

从语义的角度来看,你可以说IDisposable的需要是一个实现细节,与你班级的实际合同无关。

您可以做的是将对象投放到IDisposable并仅调用Dispose(),如果它实现了IDisposable

var disposable = foo as IDisposable;

if (disposable != null)
    disposable.Dispose();

但在这种情况下,我会按照你的建议继续使用接口继承。它不是最干净的方法,但能完美地完成工作并且需要更少的代码。