控制反转(Ioc)的设计原则
--减轻组件间的依赖性及藕合性的设计原则
作者:Make 创建日期:2005-07-24
导读
1.缘由
2、回顾面向对象思想
3.什么是Ioc
4、现行的几种实现方式
5.结论
6.附录
一、缘由
“万事万物皆有姻缘”,这一句话本是佛家偕语。不过笔者认为,这一句话也真是道出了世间万事万物的相辅相成的最彻底的一句解释。在IT这一行,更新换代比光速还快,我想同仁们都不会反驳我这句话吧!要不试试,从艺术性的工作,到工程化的项目,从面向过程到面向对象,从面向对象到面向方面!每一种思想都是那么的伟大,每一种思想都没有任何一个人(还真是任何一个人,不信的话,你找几个大师级的人物问问,他们对哪一种思想完全理解并应用了?)完全理解并应用他,但新的思想又出来了(这种思想说的是软件类的思想,编程的思想,当然没有孔子孟子之类说)!好像说了这么多,跟“万事万物皆有姻缘”没有任何关系一样,有,当然有,虽然这么多的思想没有任何一个人完全贯通使用,但提出一种新的思想来使用,这是事物发展的需要,也是必然的趋势,艺术性的编程不能实用于大型应用,因此提出工程化,面向过程使软件升级特别困难,因此懒惰的人们提出了面向对象的复用思想
,但面向对象的思想还是复杂,懒惰的人们就想要做更少的工作,因此提出了面向方面!“万事万物皆有姻缘”因为人们的懒惰,所以该放下的就放下了,重新拿起新的事物!那么为什么现在在编程界又提出了控制反转(Ioc)呢?下面我们看一个经常引用的例子:
public Class MyClass{
Logger _logger=Logger.getLogger(this.getClass());//实例化_logger
public void helloWorld(String){
_logger.DEBUG("Start print .....");
System.out.println("Hello! The world!");
_logger.DEBUG("End print.......");
}
}
现在想,如果我实例化_logger的方式变了,变成了:
Logger _logger=Logger.getLogger("My Class DEBUG");
你们想想是不是应该要改上面这个已经实现了的CLASS呢?结果是肯定的,如果我有10个类,100个,那是不是要改10次,100次,我们称这样的软件开发为藕合性太强或依赖太深!
“万事万物皆有姻缘”,控制反转(Ioc)就是为了解决这样的问题而提出的原则!
二、面向对象思想回顾
首先我们回顾面向对象思想的一些内容,笔者在《软件工程之面向对象软件工程基础(软件工程实践之三)》一文中概术面向对象时,面向对象=类+对象+继承+通信,面向对象就是这样的一种思想。将组件分类,使用时再实例化,类与类之间可以继承,他们通过通信联系。在这里我们要重新到一个概念是服务,在很多面向对象文章中都提到了服务,那么什么是服务呢?即一个类向另一个类提供他想要的接口(或方法)。
如下例:
public ClassA{
/*
*下面是ClassA提供给其它类使用的接口
*/
public void bussiness(){
System.out.println("execute bussiness");
}
}
public ClassB{
ClassA classA=new ClassA();//classA即将向ClassB提供服务
public executebussiness(){
classA.bussiness();//调用了ClassA的bussiness方法来得到服务
}
}
另两个概念就是服务提供者与服务使用者,从上例可以看出,ClassA就是服务提供者-提供业务服务的一方 ,ClassB就服务使用者(也称消费者)-使用业务服务的一方,在他们之间采用的联系的方式我们叫做通信。 从上面的例子可以看出,服务提供者提供服务给消费者是特别直接的。这样有如下坏处:
如果服务提供者变了呢?这样是不是需要改动每个服务消费者? 这样的一种依赖关系?我们用什么来解决呢?Ioc,控制反转,它让服务消费者不直接依赖于服务提供者!
三、什么是控制反转(Ioc)?
一种让服务消费者不直接依赖于服务提供者一 种组件设计方式,一种减少类与类之间依赖的设计原则,一种使服务与服务提供者完全分开的设计原则。我们将第一个例子改进一下:
public Class MyClass{
Logger _logger;
public void setLogger(Logger logger){
this._logger=logger;
}
public void helloWorld(){
_logger.DEBUG("Start DEBUG print....");
System.out.println(“hello world");
_logger.DEBUG("End DEBUG print.....");
}
}
现在调用时:
public Class UseLogger{
Logger _logger=Logger.getLogger(this.getClass());
public void execute(){
MyClass myClass=new MyClass();
myClass.setLogger(_logger);
myClass.helloWorld();
}
}
这样,我们发现,整个使用Logger的控制权全部在客户端,即Logger给MyClass提供的服务的方式已经提交给了最终客房,完全取决于客户端的需要,而不是在MyClass调用服务时就依赖于Logger了,这样,服务提供者(Logger)与消费者(MyClass)之间的依赖就少了很多。这就是Ioc的一种具体实现方式。
我们可以看出来,Ioc更通俗的一种解释就是:我在需要服务时,才告诉你怎么去给我提供服务_logger的定义在MyClass中只是一个预留的定义,直到UseLogger最终消费时才将具体怎么使用Logger通知给MyClass.
四、控制反转的几种设计方式?
目前控制反转的几种实现方式:
.基于方法的(Method-based Ioc,Type-0)
.基于接口的(Interface-based Ioc,Type-1)
.基于设值的(Setter-based Ioc,Type-2)
.基于构造的(Construtor-based Ioc,Type-3)
.Type-0
基于方法的实现,主要依赖的是接口,,服务提供者将自己的接品传递给消费者方法,而不是将具体的实现类型传递过去,如下:
public interface MyClass{
public void helloWorld(Logger _logger);
}
调用时:
Logger _logger=Logger.getLogger(this.getClass());
MyClass myClass=new MyClassImpl();
myClass.helloWorld(_logger);
从上面可以看出,这样Logger与MyClass的具体服务都依赖于接口MyClass,Logger提供服务时也止于方法上,Logger服务提供与
MyClassImpl消费之间隔开了,
.Type-1
基于接口的实现,主要是采用容器来管理服务提供者,消费者只要实现服务提供者的接口就可以达到服务的目的了。
如下:
Public Class MyClassImpl implements MyClass,Logger {
protected Logger _logger;
/*
*实现Logger的enableLogger有效方法
*/
public void enableLogger(Logger logger){
_logger=logger;
}
public void helloWorld(){
_logger.DEBUG("ENABLE");
}
}
怎么调用 :
MyClass myClass=new MyClass();
Logger _logger=Logger.getLogger(this.getClass());
Container.enableLogger(myClass,_logger);
myClass.helloWorld();
可以看出,这样的实现,必须要有珍上容器来检查是否实现了Logger接品,如果实现凶才能有效,否则就没有作用。这样的方法大大的减少了类与类之间的依赖.但必须要实现一个容器。而且发现,每一个实现的类都直接跟服务提供者(本例就是Logger)的接口有了很直接的联系。
.Type-2
的方式,就是通过BEAN的setter方法来给成员变量赋值,我们采用这种方式,就可以通过一个配置文件,配置好相应的Bean,然后通过一个容器来得到这个服务Bean,这样组件之间的依赖就已经少了。
如:
public Class MyClass{
private Logger logger;
public void setLogger(Logger logger){
this.logger=logger;
}
public void helloWorld(){
logger.DEBUG("ENABLE");
}
}
如Spring采用的方式就是如此,它的全过程如下:
配置文件:
<Beans>
<Bean id="logger" Class="Logger"/>
<Bean id="myClass" Class=MyClass">
<property name="logger"><ref bean="logger"/></property>
</Bean>
</Beans>
调用:
InputStream is=Client.class.getClassLoader().getResourceAsStream("bean.xml");
BeanFactory beans=new XMLBeanFacotory(is);
MyClass myClass=(MyClass)beans.getBean("myClass");
myClass.helloWorld();
从上面可以看出,所有的服务提供类及消费类都已经通过一个容器类来提取配置文件统一管理了。
.Type-3
基于构造的Ioc,顾名思义,就是通过构造子来传递服务提供者的具体实例来实例化服务接口。
如下:
public Class MyClass{
private Logger _logger;
public MyClass(Logger logger){
_logger=logger;
}
public void helloWorld(){
_logger.DEBUG("ENABLE");
}
}
这样,注册服务组件时在构造方法处完成,但,这样一来继承和构造时都有一定的困难。
五、结语
Ioc的一个真正的目的就是移植,减少组件的依赖性!但我们通过上面的例子,有没有发现,这中间的依赖还很大呢?比如:如果我要将Logger类移植使用另外一个公司的产品的时候,这个时候,要移植的量是不是还很大呢?
六、附录
1、术语
控制反转(Ioc-Inversion Of Control);
容器(container),用于组件创建,生存的环境;
框架(framework::一组用于对特定领域构造的可复用的基础组件
分享到:
相关推荐
【Android应用开发中控制反转IoC设计模式使用教程】 IoC(Inversion of Control,控制反转)是一种设计模式,常被称为依赖注入(Dependency Injection,DI)。在Android应用开发中,IoC模式能够显著降低组件之间的...
在软件开发中,IoC(Inversion of Control,控制反转)是一种设计模式,它将对象的创建和管理责任从代码中剥离出来,交由一个容器来处理。Spring框架是Java平台上的一个核心组件,其核心特性就是依赖注入...
### Spring IOC控制反转详解 #### 一、Spring框架简介 Spring框架是一个开源的Java平台,提供了全面的基础架构支持,让开发者能够轻松地开发出松耦合的应用程序。它通过依赖注入(Dependency Injection, DI)和...
"IoC(控制反转)"是软件设计模式中的一个重要概念,它在现代软件开发,特别是.NET框架下的C#编程中占据了核心地位。控制反转的主要思想是将对象之间的依赖关系从代码内部转移到外部容器,从而使代码更加灵活、可...
spring IOC控制反转 spring IOC控制反转 spring IOC控制反转
在Spring Boot框架中,控制反转(Inversion of Control,简称IOC)是一种重要的设计原则,它将对象的创建和管理权交给容器(在这里是Spring框架),从而解耦了应用的组件。面向接口编程则是另一种核心原则,它提倡...
本文介绍了Spring框架中的控制反转IOC和依赖注入DI,欢迎阅读,共同学习,一起进步。 Spring框架基础参考:深入学习Spring基础 文章目录一.入门程序和IOC简介二.IOC-控制反转三.DI-依赖注入四. IOC和DI五.Spring...
**Spring技术--IOC控制反转** 在Java开发领域,Spring框架以其强大的功能和广泛的应用而闻名。其中,IOC(Inversion of Control,控制反转)是Spring的核心特性之一,它改变了传统对象创建和管理的方式,实现了依赖...
本文文档中有 控制反转 DI依赖注入,希望可以给大家在技术上有一点的帮助
控制反转(IOC,Inversion of Control)是一种设计模式,它在软件工程中被广泛应用,特别是在Java开发中。IoC的核心思想是将对象的创建和管理权交给一个外部容器,而不是让对象自行创建和管理依赖。这有助于降低耦合...
IOC,即控制反转,是一种设计思想,在Java开发领域中,它主要被用来消除程序之间的依赖性,使得类的设计更加灵活。传统的编程模式下,一个类会通过new关键字创建其依赖对象,这种方式会导致耦合度较高,不利于后期的...
IOC(Inversion of Control,控制反转)是一种设计原则,它改变了传统程序设计中对象之间的依赖关系。在没有IOC的情况下,一个对象通常会自行创建或查找它需要协作的对象,这导致了对象间的紧密耦合。然而,IOC通过...
控制反转是一种设计原则,它的主要思想是将对象的创建和管理权交给容器,而不是由对象自身负责。在传统的编程模式中,一个对象需要另一个对象时,通常会自行创建或寻找。而在IOC中,对象不再直接创建依赖对象,而是...
基于annotation注解方式理解SpringIOC控制反转
IoC是一种设计原则,旨在减少组件之间的耦合度,提高代码的可维护性和可测试性。在传统的编程模式中,组件或对象之间通过调用其他对象的方法或属性来进行交互,这种直接的调用关系导致了高度的耦合性。而在IoC模式下...
Spring IOC(Inversion of Control,控制反转)是Spring框架的核心特性,它改变了传统Java应用程序中对象的创建和管理方式。在传统的程序设计中,我们通常手动创建对象并管理它们之间的依赖关系,而在Spring中,这些...
IoC,即"Inversion of Control"(控制反转),是软件工程领域的一个重要概念,特别是面向对象编程中的一个关键设计原则。从字面上理解,IoC指的是程序运行时控制流的方向发生了“反转”。传统的程序设计中,应用程序...
**Spring控制反转(IoC)理解** Spring框架的核心特性之一是控制反转(Inversion of Control,简称IoC),也常被称为依赖注入(Dependency Injection,简称DI)。IoC是一种设计模式,它将对象的创建和管理从应用代码...
Spring.NET 控制反转(Inversion of Control,英文缩写为IoC),也叫依赖注入(Dependency Injection)。我个人认为控制反转的意思是依赖对象(控制权)发生转变,由最初的类本身来管理依赖对象转变为IoC框架来管理...