控制反转(IOC)

控制反转(IOC)是一种编程模式,主要目的是降低组件间的耦合度。它将对象的创建和管理交给专门的容器,使得组件不再直接创建依赖对象。依赖注入(DI)是IOC的一种实现方式,通过接口、setter方法或构造函数将依赖关系传入组件。这种方式使得系统更加灵活,易于扩展。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

控制反转( IOC )

       控制反转的英文全称是Inversion ofControl (简称I0C),是近年来兴起的一种Java编程模式。该编程思想主要用于协调组件之间相互依赖关系,是面向对象思想的一种具体表现形式。

什么是控制反转

      有一句好莱坞名言可以准确地概括出控制反转的本质:“Don't call us, we'll call you”(你呆着别动,到时我会找你)

      控制:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IOC是有专门一个容器来创建这些对象,即由IOC容器来控制对象的创建
      反转:传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象。为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转。


       先简单回顾面向对象的思想。面向对象=类+对象+继承+消息,面向对象将组件分类,使用时再实例化,类与类之间可以继承,它们通过消息互相联系。另一个要提到的概念是服务,在很多面向对象文章中都涉及到了这个概念,那么什么是服务呢?服务就是一个类向另一个类提供该类所需要的接口(或方法)。下面通过一个简单的例子展示面向对象的思想,具体代码如下:

 class Computer {
	CPU cpu = new CPU();
	public void computerwork() {
		cpu.cpuwork();
	}
	
}
 
 class CPU {
	 public void cpuwork() {
		 System.out.println("computer is working");
	 }
 }

       上段代码中定义了一一个Computer类和一个CPU类,Computer类要引用CPU类。在这里另外定义两个概念:服务提供者服务使用者。从上面的例子可以知道CPU类是服务的提供者,而对应的Computer类就是服务使用者。在它们之间采用的联系方式称为消息。

       从上面的例子可以看出,服务提供者提供服务给服务使用者是采用直接调用的方式。这样带来如下弊端:如果服务提供者接口发生了变化,这样是不是需要改动每个服务使用者?这样的种依赖关系如何来解决呢?答案就是控制反转,它的引入让服务使用者不直接依赖于服务提供者。

      从上面的例子可以看出,传统的软件架构中,由程序内部代码来控制组件之间的关系。我们经常使用new关键字来实现两组件间关系的组合,这种实现的方式会造成组件之间互相耦合。控制反转能很好地解决该问题,它将实现组件间的关系从程序内部提到外部容器来管理。也就是说,由容器在运行期将组件间的某种依赖关系动态地注入组件中。控制程序间关系的实现交给了外部的容器来完成。

     注意: 一个好的设计,不但要实现代码重用,还要将组件间关系解耦。

       控制反转是一种让服务使用者不直接依赖于服 务提供者的一种组件设计方式,一种减少类与类之间依赖和耦合的设计原则,一种使服务与服务提供者完全分开的设计原则。下面对于同一个代码架构例子采用IOC的思想再实现一次, 具体代码如下所示::

 class Computer {
	CPU cpu;
	public void setCpu(CPU cpu) {
		this.cpu=cpu;
	}
	public void computerwork() {
		cpu.cpuwork();
	}
	
}
 
 class CPU {
	 public void cpuwork() {
		 System.out.println("computer is working");
	 }
 }
 
 public class client {
	 CPU cpu = new CPU();
	 public void execute() {
		 Computer com = new Computer();
		 com.setCpu(cpu);
		 com.computerwork();
	 }
 }
 

       观察以上代码可以发现,整个CPU类的控制权全部在客户端程序,即CPU给提供的服务方式最后提交给了客户端,完全取决于客户端的需要。不再是Computer 调用服务时就依赖于CPU。服务提供者(CPU)与使用者(Computer)之间的依赖就少了很多。  这就是IOC的一种具体实现方式。可以看出,I0C 更通俗的一种解释就是“ 在需要服务时才告诉你怎么去提供服务”。CPU的定义在Computer中只是一个预留的定义,直到client最终使用时才将具体怎么使用CPU通知给Computer。
       了解了控制反转的含义后,再回到开始总结的那句话:“Don't call us, we'll call you”觉得这句话对IOC的形容非常贴切、生动。

控制反转的设计方式


最常用的控制反转的设计方式主要有3种。

(1)基于接口的设计方式

(2)基于JavaBeans的setter方法的设计方式,如:Spring框架。

(3)基于构造函数的设计方式,即通过构造函数传递服务提供者作为参数实现。

总结:可以发现使用IOC带来的代价是:需要在客户端或其他某处进行Computer和CPU之间联系的组装。所以,IOC并不是消除了Computer和CPU之间固有的联系,而只是转移了这种联系。

IOC和DI(Dependency Injection)

        组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

        关系:依赖注入不能单独存在,需要在IOC基础上完成操作

 

 

### 控制反转 (IoC) 和依赖注入 (DI) #### 控制反转 (IoC) 控制反转是一种设计原则,用于减少计算机程序之间的耦合程度。在传统编程模式下,程序员负责创建和管理对象及其依赖关系;而在控制反转的设计中,这些控制权被转移到外部容器或框架,程序员只需关注业务逻辑,具体的对象创建和管理由容器负责[^2]。 这种转移意味着应用组件不再直接创建所依赖的服务或其他资源,而是通过某种方式声明其需求,让外部环境提供所需服务。这种方式提高了代码的灵活性、可测试性和复用性[^4]。 #### 依赖注入 (DI) 依赖注入是实现控制反转的一种具体方法。它允许一个类将其依赖项(通常是接口形式)作为参数传递给另一个类,而不是内部硬编码创建这些依赖项的对象实例。这不仅降低了模块间的紧耦合度,还增强了系统的可扩展性和维护性。 依赖注入可以通过多种方式进行: - **构造函数注入**: 将依赖项通过构造函数传入目标对象; - **Setter 方法注入**: 使用 setter 方法设置属性值; - **字段注入**: 直接为私有成员变量赋值(通常不推荐)。 #### Spring 的 IoC 容器 Spring 框架提供了强大的 IoC 容器来管理和装配 Bean 及其相互间的关系。当开发者定义了一个 Bean 并指定了它的依赖之后,Spring 容器会在运行时自动完成相应的初始化工作并解决所有的依赖问题。 对于如何配置 Bean 来支持不同类型的依赖注入,Spring 支持 XML 文件、Java 类以及注解三种主要的方式来进行描述和注册Bean的信息。 ```java // 构造函数注入示例 public class Service { private final Repository repository; @Autowired // 或者省略此注解,在现代版本中默认启用 public Service(final Repository repository) { this.repository = repository; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值