IOC? IOC与DI?

阅读时长: 4 分钟 1104 字

那什么才算 IoC?我们重申一次标准:

以下从应用对象是否自行查找依赖、以及谁负责组装对象来比较:

条件是否满足解释
你不创建依赖对象✅Kitchen.createFood() or agent.getVehicle() 是“工厂”,你没直接 new
业务对象是否被外部注入依赖取决于调用位置在组装代码中手动调用 setter 也可以实现 DI,不要求必须使用容器
容器是否负责自动组装❌这些调用本身不能证明使用了容器

所以更准确地说:

示例是否 IoC?是否有 IoC 的“倾向/味道”?
Kitchen.createFood() + setFood()取决于组装位置外部调用 setter 可构成 DI
agent.getVehicle() + setVehicle()取决于组装位置业务内部查找属于 Service Locator
Spring.getBean(Food.class) 然后自动注入✅ 是✅ 容器管理依赖

一句话解释区别:

IoC 是思想(理念),DI 是具体实现方式之一。

来拆解下这两个词:

IoC(Inversion of Control)控制反转:

  • 是一种 设计思想

  • 目标是:把控制权从程序员手里“反转”给框架或容器

  • 不再由你手动控制程序流程和对象组合,而是由框架来“自动调度”

比如:

依赖对象的创建与组合交给外部完成。

DI(Dependency Injection)依赖注入:

  • 是一种 实现 IoC 的具体技术手段

  • 它的核心是:将依赖通过某种方式“注入”给目标对象

  • 有 3 种常见形式:

构造器注入

  • Setter 注入

  • 接口注入

关系总结图:

IoC 是设计思想,DI 是实现依赖组合的一种方式。

对比项IoCDI
是什么一种设计思想一种实现方式
控制谁控制“对象如何创建和依赖如何组合”的权力从你手中“反转”出去指定“依赖应该怎么注入进来”
关系包含关系:DI 是 IoC 的一种实现手段属于 IoC 的一种实践方式
举例Spring 框架控制 Bean 生命周期@Autowired 注入依赖

什么是 Service Locator?

Service Locator 是一种 设计模式,其核心目的是:

提供一个全局的服务查找器,通过它你可以在任何地方查找、获取到需要的服务或依赖对象,而不需要手动创建和管理。

换句话说,它是一个中介,负责管理对象的创建和查找。你只需要请求它来获取服务,而不用关心服务怎么创建或者存在哪儿。

核心思想:

从服务定位器(Service Locator)中获取服务,而不是自己直接管理和创建对象。

但是,这种方式的问题:

虽然 Service Locator 提供了“获取依赖”的能力,但它有一个隐含的缺点: 它破坏了“依赖显式化”的原则,也就是,你没有直接看出对象的依赖是什么,导致了代码的可维护性差,特别是当系统变得复杂时。

这和 DI 的区别:

  • DI 明确地告诉你:你需要哪些依赖,并且这些依赖会通过某种方式(构造器、setter 等)注入给你。

  • Service Locator 则是通过一个全局对象来管理和查找依赖,你在使用时不关心这些依赖怎么被创建的。

举个简单的例子:

没有 Service Locator(直接依赖注入):

public class Restaurant {
    private final Food food;

    public Restaurant(Food food) {
        this.food = food;
    }

    public void order() {
        food.eat();
    }
}

通过构造器注入 Food,明确表达了 Restaurant 依赖于 Food。当你创建 Restaurant 时,需要显式地提供 Food。

使用 Service Locator:

public class Restaurant {
    private Food food;

    public void order() {
        // 通过 Service Locator 获取 food
        food = ServiceLocator.getService(Food.class);  
        food.eat();
    }
}

在这个例子里,Restaurant 并不直接关心 Food 是怎么被创建的,它只是通过 ServiceLocator.getService(Food.class) 去查询获取 Food。 你不用显式地提供 Food,而是让 Service Locator 去处理。

Service Locator 类的简单实现:

import java.util.Map;
import java.util.HashMap;

public class ServiceLocator {
    private static Map<Class<?>, Object> services = new HashMap<>();

    // 注册服务
    public static <T> void registerService(Class<T> serviceClass, T serviceInstance) {
        services.put(serviceClass, serviceInstance);
    }

    // 获取服务
    public static <T> T getService(Class<T> serviceClass) {
        return serviceClass.cast(services.get(serviceClass));
    }
}

在这段代码中,ServiceLocator 提供了一个静态方法来获取所有注册过的服务对象,而你不需要关心这些对象是怎么创建的。

本网站已运行: 计算中...
备案 赣公网安备36072502000191 | 赣ICP备2024040374号
使用 Hugo 构建 · 主题 Stack 由 Jimmy 设计