我正在努力养成编写接口而不是实现的习惯,而在大多数情况下,我可以看到有一些原因让我感到困难。
举一个非常简单的例子:
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方法签名发生变化,我仍然需要浏览所有使用它的页面并修改代码。我错过了这一点吗?
先谢谢你的帮助, Wilky。
答案 0 :(得分:5)
在示例中,如果您使用FileAuditLogger()
或DatabaseAuditLogger()
切换EventLogAuditLogger()
,则无需重写代码即可切换实施。
通常,您使用IoC容器(Autofac,StructureMap,Unity等)自动连接对象实例。因此,您可以拨打new AuditLog()
IoC.Container.Resolve<IAuditLog>()
如果您想了解更多信息,请与我们联系。
答案 1 :(得分: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");
}
现在您可以在运行时根据某些配置注入任何类,而无需更改实际实现
答案 2 :(得分:3)
这并不一定意味着您必须实际使用C#interface
。 OOP术语中的接口是API的公开可见外观。这是一份合同,应规定外部可见的操作结果。它在表面下的工作原理应该是无关紧要的,这样你就可以随时更换实现。
当然,在这方面,interface
是一种能够使用不同实现的方法,但是抽象基类甚至是其他人可以派生的非抽象类也是如此。
但更多的是你的问题的确切点:当然,在实例化一个类时,必须知道它的类型,但你不一定要在那里创建类实例。您可以从外部设置IAuditLog
或通过工厂类等获取它,在代码中的确切位置您不知道的是,您获得的确切类型(除了它与之兼容) IAuditLog
)。
答案 3 :(得分: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
}
}