当我使用依赖注入时,我的接口和具体类之间存在一对一的关系。当我需要向接口添加一个方法时,我最终打破了实现该接口的所有类。使用接口或类进行依赖注入
这是一个简单的例子,但我们假设我需要将注入到我的一个类中。
public interface ILogger
{
void Info(string message);
}
public class Logger : ILogger
{
public void Info(string message) { }
}
这样的1对1关系就像是一种代码味道。由于我只有一个实现,如果我创建一个类并将Info
方法标记为虚拟以在我的测试中覆盖而不是仅为单个类创建接口,是否存在潜在问题?
public class Logger
{
public virtual void Info(string message)
{
// Log to file
}
}
如果我需要另一种实现中,我可以重写Info
方法:
public class SqlLogger : Logger
{
public override void Info(string message)
{
// Log to SQL
}
}
如果每个这些类的有,将创建一个漏抽象特定的属性或方法,我可以提取出的基类:
public class Logger
{
public virtual void Info(string message)
{
throw new NotImplementedException();
}
}
public class SqlLogger : Logger
{
public override void Info(string message) { }
}
public class FileLogger : Logger
{
public override void Info(string message) { }
}
我没有把基类标记为抽象的原因是因为如果我想添加另一个方法,我不会打破exis实现。例如,如果我的FileLogger
需要Debug
方法,我可以在不破坏现有SqlLogger
的情况下更新基类Logger
。
public class Logger
{
public virtual void Info(string message)
{
throw new NotImplementedException();
}
public virtual void Debug(string message)
{
throw new NotImplementedException();
}
}
public class SqlLogger : Logger
{
public override void Info(string message) { }
}
public class FileLogger : Logger
{
public override void Info(string message) { }
public override void Debug(string message) { }
}
再次,这是一个简单的例子,但是当我应该更喜欢一个接口?
_我之所以没有将基类标记为抽象是因为如果我想添加另一个method_Hm,抽象类可以包含实现。您可以将Debug方法添加到您的抽象Logger类。 – 2012-04-25 08:09:01
如果你正在编写一个可重用的库,打破现有的实现只是一个问题。你是?或者你只是写一行业务应用程序? – Steven 2012-04-25 11:03:53
这不是问题的范围,但继承被高估。 'SqlLogger'只是一个具有'SqlLogPersistenceStrategy'的具体'Logger'。在大多数情况下,构成比继承好得多。同样对于你的问题,ISP怎么样? 'ILogInfo','ILogError'等 – plalx 2015-11-05 16:28:30