深度理解依赖注入
[2] DI的实现方式
[3] Setter Injection
[4] 除了DI,还有Service Locator
2.4 除了DI,还有Service Locator
上面提到的依赖注入只是消除ServiceUser和ServiceProvider之间的依赖关系的一种方法,还有另一种方法:服务定位器(Service Locator)。也就是说,由ServiceLocator来专门负责提供具体的ServiceProvider。当然,这样的话ServiceUser不仅要依赖于服务的接口,还依赖于ServiceContract。仍然是最早提到过的电影列举器的例子,如果使用Service Locator来解除依赖的话,整个依赖关系应当如下图所示:
图3
用起来也很简单,在一个适当的位置(比如在一组相关服务即将被调用之前)对ServiceLocator进行初始化,用到的时候就直接用ServiceLocator返回ServiceProvider实例:
2ServiceLocator locator = new ServiceLocator();
3locator.loadService("MovieFinder", new ColonMovieFinder("movies1.txt"));
4ServiceLocator.load(locator);
5//服务定义器的使用
6//其实这个使用方式体现了服务定位器和依赖注入模式的最大差别:ServiceUser需要显示的调用ServiceLocator,从而获取自己需要的服务对象;
7//而依赖注入则是隐式的由容器完成了这一切。
8MovieFinder finder = (MovieFinder) ServiceLocator.getService("MovieFinder");
9
正因为上面提到过的ServiceUser对ServiceLocator的依赖性,从提高模块的独立性(比如说,你可能把你构造的ServiceUser或者ServiceProvider给第三方使用)上来说,依赖注入可能更好一些,这恐怕也是为什么大多数的IOC框架都选用了DI的原因。ServiceLocator最大的优点可能在于实现起来非常简单,如果您开发的应用没有复杂到需要采用一个IOC框架的程度,也许您可以试着采用它。
3.广义的服务
文中很多地方提到服务使用者(ServiceUser)和服务提供者(ServiceProvider)的概念,这里的“服务”是一种非常广义的概念,在语法层面就是指最普通的依赖关系(类型A中有一个B类型的变量,则A依赖于B)。如果您把服务理解为WCF或者Web Service中的那种服务概念,您会发现上面所说的所有技术手段都是没有意义的。以WCF而论,其客户端和服务器端本就是依赖于Contract的松耦合关系,其实这也从另一个角度说明了SOA应用的优势所在。
参考资料:
Object Builder Application Block