文章目录
为什么要面向接口编程
如果有以下状况
public class SomeComponent
{
public void DoWork(){
Logger logger = new Logger();
var data = GetData();
logger.Log(data);
}
}
SomeComponent类与Logger类及其实现紧密耦合。如果Logger不可用,那么SomeComponent也会不可用,更重要是——不能使用另一种日志记录器。
解决
Logger是典型的横切关注点(cross-cuttingconcern)情况。横切关注点是你需要放在类里却又与类的需求没有太大关系的功能。
当实现一个类时,可能需要日志记录、用户验证、多线程、缓存、对象池、错误处理、本地化以及数据验证等。这些方面应该是类的实现的一部分吗,还是说它们放在调用类之外更好?如果作为类的一部分,横切关注点会带来重复代码的重大风险。相反,如果按照前面那个例子的做法,横切关注点将会导致紧密依赖。
完全分离横切关注点需要使用依赖注入(DI)或服务定位器(SL)等模式,在这种情况下,类依赖的是某种抽象而不是实际编译的模块。一般而言,分离横切关注点意味着类是对接口而不是实现编程的。
public interface ILogger
{
void Log (string data);
}
public class Logger : ILogger
{
public void Log (string data)
{
...
}
}
SomeComponent类现在以某种方式接受ILogger组件的引用。这使SomeComponent类可以使用任何实现这个接口的日志记录器组件。Somecomponent类己经成功从日志记录器解耦了,得到的代码更易重用和扩展。比如说,把somecomponent的行为记录到一个数据库只需要开发一个特定的类实现这个接口以及引用注入。
重要:与这个例子和这条OOD原则密切相关的是依赖注入和服务定位器模式。两个模式都提供一种方式,向对接口编程的类传递接口实例的某个实际引用。