Paul Hammant
翻译:James Shen
摘要
Inversion of Control (逆向控制) 是一种用来解决模块(实际上也可以是简单的Java类)之间依赖关系、配置及生命周期的设计模式,其中对模块依赖关系的处理是Ioc的精华部分。
模块依赖
模块之间降低耦合度有以下好处:
增加类的复用程度 使类的测试更加容易 使整个系统更容易组装和配置
说明
运用了Ioc模式后我们不需求再自己管理模块之间的依赖关系,只需要声明这中依赖关系由容器去实现这种依赖关系。就好像把对模块之间依赖关系的控制进行了倒置,不再由模块自己来建立这种依赖关系而交给容器(例如PicoContainer、Spring)去管理。
范例
下面是一个非常简单的例子来说明Ioc模式:
public interface Orange {
// methods
}
public class AppleImpl implements Apple {
private Orange orange;
public AppleImpl(Orange orange) {
this.orange = orange;
}
// other methods
}
public class AppleImpl implements Apple{
private Orange orange;
public Apple() {
this.orange = new OrangeImpl();
}
// other methods
}
public class AppleImpl implements Apple {
private static Orange orange = OrangeFactory.getOrange();
public Apple() {
}
// other methods
}
这里的问题在于:你依赖OrangleImpl来具体实现orange接口,这样apple类就缺乏足够的灵活性。这些代码都是硬写的,不能被复用更不能通过一个classloader来生成不同的实例。
模块的配置
有时我们的配置如下:
public class BigFatComponent {
String config01;
String config02;
public BigFatComponent() {
ResourceFactory resources = new ResourceFactory(new File("mycomp.properties"));
config01 = resources.get("config01");
config02 = resources.get("config02");
}
// other methods
}
使用了Ioc模式可以优化如下:
public class BigFatComponent {
String config01;
String config02;
public BigFatComponent(String config01, String config02) {
this.config01 = config01;
this.config02 = config02;
}
// other methods
}
public interface BigFatComponentConfig {
String getConfig01();
String getConfig02();
}
public class BigFatComponent {
String config01;
String config02;
public BigFatComponent(BigFatComponentConfig config) {
this.config01 = config.getConfig01();
this.config02 = config.getConfig02();
}
// other methods
}
这样我们可以灵活的对BigFatComponentConfig有不同的实现:
直接写代码来设置配置 从XML文件读取配置 从Properties文件读取配置
根据需要我们可以选择不同的实现
模块的生命周期
模块的生命周期一般从构造函数就开始了。Ioc模式建议我们实现Startable接口通过start/stop方法来开始和结束模块,这样方便容器来控制模块的生命周期。
public class SomeDaemonComponent implements Startable {
public void start() {
// listen or whatever
}
public void stop() {
}
// other methods
}
例外情况
日志对于Ioc来说是一种例外情况,Apache下的Commons-Logging和Log4J都不支持Ioc模式。他们典型的用法是在应用程序中静态的直接调用,PicoContainer不建议我们对日志模块进行复用。