【问题标题】:Program to an interface not an implementation confusion对接口编程而不是实现混乱
【发布时间】:2012-06-29 11:02:25
【问题描述】:

我正在努力养成编写接口而不是实现的习惯,虽然在大多数情况下,我可以看出其中的原因,但有一些地方我很挣扎。

举这个非常简单的例子:

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 方法签名发生变化,我仍然必须浏览所有使用它的页面并修改代码。我没有抓住重点吗?

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

【问题讨论】:

    标签: c# oop interface


    【解决方案1】:

    在示例中,如果您将 FileAuditLogger() 切换为 DatabaseAuditLogger()EventLogAuditLogger(),则可以切换实现而无需重写代码。

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

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

    【讨论】:

      【解决方案2】:

      假设有两个 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");
      }
      

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

      【讨论】:

      • 谢谢阿西夫。很有道理。
      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

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

        所以,不要使用这段代码:

        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
            }    
        }
        

        【讨论】:

          猜你喜欢
          • 2011-10-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多