1

我正在尝试养成对接口而不是实现进行编码的习惯,虽然在大多数情况下,我可以看到其中的一些原因我很挣扎。

举这个非常简单的例子:

public interface IAuditLog
{
    void AddLog(string log);
}

public class AuditLog : IAuditLog
{
    public void AddLog(string log)
    {
        //implementation
    }
}

调用审计日志类:

public partial class AuditLogPage : System.Web.UI.Page
{
    protected void btnAddLog_Click(object sender, EventArgs e)
    {
        IAuditLog objAuditLog = new AuditLog();
        objAuditLog.AddLog("test log");
    }
}

我在实例化的时候还是要使用 AuditLog 的,那有什么意义呢?如果 AddLog 方法签名发生变化,我仍然需要浏览所有使用它的页面并修改代码。我错过了重点吗?

提前感谢您的帮助,威尔基。

4

4 回答 4

5

在示例中,如果您FileAuditLogger()使用DatabaseAuditLogger()或者EventLogAuditLogger()您可以切换实现而无需重写代码。

通常,您会使用 IoC 容器(Autofac、StructureMap、Unity 等)来自动连接对象实例化。所以new AuditLog()你会打电话而不是打电话IoC.Container.Resolve<IAuditLog>()

如果您想了解更多信息,请告诉我。

于 2012-06-29T11:06:42.573 回答
4

假设有两个 AuditLog 类

class AuditLogToDatabase : IAuditLog // writes to database

另一个是

class AuditLogToFile : IAuditLog // writes to file

喜欢

protected void btnAddLog_Click(object sender, EventArgs e)
{
    IAuditLog objAuditLog = AuditLogFactory.GetAuditLog();
    objAuditLog.AddLog("test log");
}

现在您可以在运行时基于某些配置注入任何类,而无需更改实际实现

于 2012-06-29T11:06:19.437 回答
3

这并不一定意味着您必须实际使用 C# interface。OOP 术语中的接口是 API 的公开可见外观。这是一份合同,应指定外部可见的运营结果。它在表面下究竟是如何工作的应该是无关紧要的,这样您就可以随时更换实现。

当然,在这方面,aninterface是一种能够使用不同实现的方法,但抽象基类甚至是其他人可以派生的非抽象类也是如此。

但更确切地说是您的问题:当然,在实例化一个类时,它的类型必须是已知的,但您不一定必须在那里创建类实例。您可以IAuditLog从外部设置一个或通过工厂类等获取它,在代码中的那个确切点,您不知道您获得的确切类型(除了它与 兼容IAuditLog)。

于 2012-06-29T11:06:08.513 回答
1

当您从方法创建实例时,这实际上很有用,AuditLog比如Factory方法,并且您有多个从接口AuditLogXXX派生的类。IAuditLog

因此,不要使用此代码:

IAuditLog objAuditLog = new AuditLog();

当您对接口进行编程时,您实际上会使用此代码:

IAuditLog objAuditLog = LogFactory.GetAuditLog(); //This call is programmed to an interface

其中GetAuditLog()是在类上定义的接口类型方法LogFactory,如下所示:

class LogFactory
{    
    public IAuditLog GetAuditLog() // This method is programmed to an interface
    {
        //Some logic to make a choice to return appropriate AuditLogXXX instance from the factory
    }    
}
于 2012-06-29T11:16:16.643 回答