IOC? IOC与DI?

阅读时长: 4 分钟 1017 字

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

真正的控制反转需要满足这三个条件:

条件是否满足解释
你不创建依赖对象✅Kitchen.createFood() or agent.getVehicle() 是“工厂”,你没直接 new
你不注入依赖对象❌你手动调用 setFood() 或 setVehicle(),控制权仍在你手中
容器/外部框架控制依赖注入流程❌没有任何容器帮你自动注入

✅ 所以更准确地说:

示例是否 IoC?是否有 IoC 的“倾向/味道”?
Kitchen.createFood() + setFood()❌ 不是✅ 有工厂感
agent.getVehicle() + setVehicle()❌ 不是✅ 有 service locator 的风格
Spring.getBean(Food.class) 然后自动注入✅ 是✅ 真正的 IoC

🧠 一句话解释区别:

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

🔍 来拆解下这两个词:

✅ IoC(Inversion of Control)控制反转:

  • 是一种 设计思想

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

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

比如:

你不自己 new,不自己调用 set,框架帮你搞定一切

✅ DI(Dependency Injection)依赖注入:

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

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

  • 有 3 种常见形式:

构造器注入

  • Setter 注入

  • 接口注入

✅ 关系总结图:

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

## ✅ 什么是 Service Locator?

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

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

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

### 🧠 核心思想:

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

### 🚨 但是,这种方式的问题:

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

### 这和 DI 的区别:

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

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

## ✅ 举个简单的例子:

### 1️⃣ 没有 Service Locator(直接依赖注入):

```java
public class Restaurant {
    private final Food food;

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

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

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

2️⃣ 使用 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 类的简单实现:

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

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

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

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

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