什么是控制反转(IOC)
public class UserServiceTest { public static boolean doTest() { // ... } public static void main(String[] args) {//这部分逻辑可以放到框架中 if (doTest()) { System.out.println("Test succeed."); } else { System.out.println("Test failed."); } } }
上面代码所有代码都由开发人员控制
控制反转例子
public abstract class TestCase { public void run() { if (doTest()) { System.out.println("Test succeed."); } else { System.out.println("Test failed."); } } public abstract boolean doTest(); } public class JunitApplication { //容器 private static final List<TestCase> testCases = new ArrayList<>(); //往容器注入实现 public static void register(TestCase testCase) { testCases.add(testCase); } public static final void main(String[] args) { //循环调用 for (TestCase case:testCases){ case.run(); } } }
以上代码是一个简单的测试框架例子代码
使用
public class UserServiceTest extends TestCase { @Override public boolean doTest() { // ... } } // 注册操作还可以通过配置的方式来实现,不需要程序员显示调用register() JunitApplication.register(new UserServiceTest();
新增一个用户的实现
控制反转 控制代表框架 将由开发人员控制执行流程 反转给框架
依赖注入(DI)
不要将类依赖的对象 使用直接new的方式初始化,应在外部初始化 然后通过构造函数或者方法注入使用
// 非依赖注入实现方式 public class Notification { private MessageSender messageSender; public Notification() { this.messageSender = new MessageSender(); //此处有点像hardcode } public void sendMessage(String cellphone, String message) { //...省略校验逻辑等... this.messageSender.send(cellphone, message); } } public class MessageSender { public void send(String cellphone, String message) { //.... } } // 使用Notification Notification notification = new Notification(); // 依赖注入的实现方式 public class Notification { private MessageSender messageSender; // 通过构造函数将messageSender传递进来 public Notification(MessageSender messageSender) { this.messageSender = messageSender; } public void sendMessage(String cellphone, String message) { //...省略校验逻辑等... this.messageSender.send(cellphone, message); } } //使用Notification MessageSender messageSender = new MessageSender(); Notification notification = new Notification(messageSender);
依赖注入框架(DI Framework)
在现实开发中 一个类可能依赖几十个上百个类,如果都采用手动new的方式 代码会非常臃肿和复杂
现成的依赖注入框架有很多,比如 Google Guice、Java Spring、Pico Container、Butterfly Container 等。不过,如果你熟悉 Java Spring 框架,你可能会说,Spring 框架自己声称是控制反转容器(Inversion Of Control Container)
将创建对象的和管理对象声明周期的控制权交给反转给框架 通过DI解决类与类之间依赖关系
依赖反转原则(DIP)
同时也叫依赖倒置原则
高层模块(high-level modules)不要依赖低层模块(low-level)。高层模块和低层模块应该通过抽象(abstractions)来互相依赖。除此之外,抽象(abstractions)不要依赖具体实现细节(details),具体实现细节(details)依赖抽象(abstractions)。