Ioc模式(又称DI:Dependency Injection)
分离关注( Separation of Concerns : SOC)是Ioc模式和AOP产生最原始动力,通过功能分解可得到关注点,这些关注可以是 组件Components, 方面Aspects或服务Services。
从GoF设计模式中,我们已经习惯一种思维编程方式:Interface Driven Design 接口驱动,接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性等等,但是接口一定是需要实现的,也就是如下语句迟早要执行:
AInterface a = new AInterfaceImp();
AInterfaceImp是接口AInterface的一个子类,Ioc模式可以延缓接口的实现,根据需要实现,有个比喻:接口如同空的模型套,在必要时,需要向模型套注射石膏,这样才能成为一个模型实体,因此,我们将人为控制接口的实现成为“注射”。
Ioc英文为 Inversion of Control,即反转模式,这里有著名的好莱坞理论:你呆着别动,到时我会找你。后被Martin Fowler改名为 Dependency Injection 依赖注射,也就是将类之间的关系通过第三方进行注射,不需要类自己去解决调用关系。
其实Ioc模式也是解决调用者和被调用者之间的一种关系,上述AInterface实现语句表明当前是在调用被调用者AInterfaceImp,由于被调用者名称写入了调用者的代码中,这产生了一个接口实现的原罪:彼此联系,调用者和被调用者有紧密联系,在UML中是用依赖 Dependency 表示。
但是这种依赖在分离关注的思维下是不可忍耐的,必须切割,实现调用者和被调用者解耦,新的Ioc模式 Dependency Injection 模式由此产生了, Dependency Injection模式是依赖注射的意思,也就是将依赖先剥离,然后在适当时候再注射进入。
Ioc模式(Dependency Injection模式)有三种:
第一种类型 |
从JNDI或ServiceManager等获得被调用者,这里类似ServiceLocator模式。 |
1. EJB/J2EE 2. Avalon(Apache的一个复杂使用不多的项目) |
第二种类型 |
使用JavaBeans的setter方法 |
1. Spring Framework, 2. WebWork/XWork |
第三种类型 |
在构造方法中实现依赖 |
1. PicoContainer, 2. HiveMind |
有过EJB开发经验的人都知道,每个EJB的调用都需要通过JNDI寻找到工厂性质的Home接口。
在通常传统情况下,为了实现调用者和被调用者解耦,分离,一般是通过工厂模式实现的,下面将通过比较工厂模式和Ioc模式不同,加深理解Ioc模式。
工厂模式和Ioc
假设有两个类B 和 C:B作为调用者,C是被调用者,在B代码中存在对C的调用:
public class B{ private C comp; ...... }
|
实现comp实例有两种途径:单态工厂模式和Ioc。
工厂模式实现如下:
public class B{ private C comp; private final static MyFactory myFactory = MyFactory.getInstance();
public B(){ this.comp = myFactory.createInstanceOfC();
} public void someMethod(){ this.comp.sayHello(); } ...... }
|
特点:
- 每次运行时,MyFactory可根据配置文件XML中定义的C子类实现,通过createInstanceOfC()生成C的具体实例。
使用Ioc依赖性注射( Dependency Injection )实现Picocontainer如下,B类如同通常POJO类,如下:
public class B{ private C comp; public B(C comp){ this.comp = comp; } public void someMethod(){ this.comp.sayHello(); } ...... }
|
假设C接口/类有有一个具体实现CImp类。当客户端调用B时,使用下列代码:
public class client{ public static void main( String[] args ) { DefaultPicoContainer container = new DefaultPicoContainer(); container.registerComponentImplementation(CImp.class); container.registerComponentImplementation(B.class); B b = (B) container.getComponentInstance(B.class); b.someMethod(); } }
|
因此,当客户端调用B时,分别使用工厂模式和Ioc有不同的特点和区别:
主要区别体现在B类的代码,如果使用Ioc,在B类代码中将不需要嵌入任何工厂模式等的代码,因为这些工厂模式其实还是与C有些间接的联系,这样,使用Ioc彻底解耦了B和C之间的联系。
使用Ioc带来的代价是:需要在客户端或其它某处进行B和C之间联系的组装。
所以,Ioc并没有消除B和C之间这样的联系,只是转移了这种联系。
这种联系转移实际也是一种分离关注,它的影响巨大,它提供了AOP实现的可能。
Ioc和AOP
AOP我们已经知道是一种面向切面的编程方式,由于Ioc解放自由了B类,而且可以向B类实现注射C类具体实现,如果把B类想像成运行时的横向动作,无疑注入C类子类就是AOP中的一种Advice,如下图:
通过下列代码说明如何使用Picocontainer实现AOP,该例程主要实现是记录logger功能,通过Picocontainer可以使用简单一行,使所有的应用类的记录功能激活。
首先编制一个记录接口:
public interface Logging {
public void enableLogging(Log log);
}
|
有一个LogSwitcher类,主要用来激活具体应用中的记录功能:
import org.apache.commons.logging.Log; public class LogSwitcher { protected Log m_log; public void enableLogging(Log log) { m_log = log; m_log.info("Logging Enabled"); } } |
一般的普通应用JavaBeans都可以继承这个类,假设PicoUserManager是一个用户管理类,代码如下:
public class PicoUserManager extends LogSwitcher {
..... //用户管理功能 } public class PicoXXXX1Manager extends LogSwitcher {
..... //业务功能 } public class PicoXXXX2Manager extends LogSwitcher {
..... //业务功能 }
|
注意LogSwitcher中Log实例是由外界赋予的,也就是说即将被外界注射进入,下面看看使用Picocontainer是如何注射Log的具体实例的。
DefaultPicoContainer container = new DefaultPicoContainer(); container.registerComponentImplementation(PicoUserManager.class); container.registerComponentImplementation(PicoXXXX1Manager.class); container.registerComponentImplementation(PicoXXXX2Manager.class); .....
Logging logging = (Logging) container.getComponentMulticaster();
logging.enableLogging(new SimpleLog("pico"));//激活log
|
由上代码可见,通过使用简单一行logging.enableLogging()方法使所有的应用类的记录功能激活。这是不是类似AOP的advice实现?
总之,使用Ioc模式,可以不管将来具体实现,完全在一个抽象层次进行描述和技术架构,因此,Ioc模式可以为容器、框架之类的软件实现提供了具体的实现手段,属于架构技术中一种重要的模式应用。
分享到:
相关推荐
在这个“IOC模式 c#经典例子”中,我们可以看到如何使用Unity,一个流行的.NET框架,来实现依赖注入。 Unity是Microsoft提供的一个轻量级的DI容器,它可以帮助开发者管理对象的生命周期,并在运行时将依赖关系注入...
### Ioc模式与微容器详解 #### Ioc模式概述 Ioc(Inversion of Control,控制反转)是一种软件设计模式,其核心理念在于通过将组件之间的依赖关系进行解耦,从而实现更为灵活、可扩展的系统架构。在传统的程序设计...
首先,IOC模式的核心思想是将对象的创建和组装的权利从对象本身转移到外部容器。这种模式也被称为Dependency Injection(依赖注入),它强调的是对象间的依赖关系由容器负责管理和注入,而不是由对象自身负责。这样...
### 基于Ioc模式的软件开发框架重构 #### 引言 控制反转(Inversion of Control,IoC)模式及其相关技术如依赖注入(Dependency Injection),在现代软件开发中扮演着至关重要的角色。IoC模式的核心在于通过将对象...
IOC模式是一种设计模式,它将对象的创建和依赖关系的管理从代码中分离出来,使系统更加灵活、可维护和可测试。在这个主题中,我们将深入探讨Java反射和动态代理如何帮助我们实现IOC。 首先,让我们理解Java反射。...
Ioc模式解析 - JAVA - 技术天地 - 赛迪网.htm
本文中,作者深入探索IOC模式的工作原理,给它一个更能描述其特点的名字——“依赖注入”(Dependency Injection),并将其与“服务定位器”(Service Locator)模式作一个比较。不过,这两者之间的差异并不太重要,...
IoC模式,即控制反转(Inversion of Control)模式,是一种优秀的组件解耦模式,其目的在于降低软件系统中各个组件之间的耦合度,从而提高系统的可维护性和可扩展性。IoC的核心思想是将依赖对象的创建和管理权从应用...
在Android应用开发中,IoC模式能够显著降低组件之间的耦合度,提高代码的可维护性和可扩展性。本文将详细介绍如何在Android应用中实现IoC,主要关注依赖注入的实践。 1. **理解IoC** IoC的核心思想是将对象的创建...
IoC模式的实现之一是依赖注入(Dependency Injection),这是一种依赖关系的交付方式。在依赖注入中,对象的依赖关系是通过构造器参数、工厂方法的参数或者属性被注入到对象中,而不是由对象在运行时自行创建其依赖...
而IoC模式通过将对象的创建和依赖关系的管理交由外部容器处理,从而实现了控制权的反转。在IoC模式下,对象不再负责创建或查找其依赖项,而是将这种责任委托给了IoC容器。这样做的好处在于: - **降低耦合度**:...
而在IoC模式下,这种控制权被反转,Girl不再直接创建Boy,而是由外部容器(如Spring框架中的ApplicationContext)负责创建和管理Boy,然后将Boy注入到Girl中。 IoC的几种类型: 1. IOC type 0:没有使用IoC,对象...
IOC 是一种软件设计模式,用于将软件系统中的对象耦合度降低。Spring 框架采用的 IOC 模式是通过一个容器来管理对象之间的依赖关系。 本文的目标是分析 Spring 框架如何实现将资源配置(以 xml 配置为例)通过加载...
控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题。 控制反转还有一个名字叫做依赖注入(Dependency Injection)。简称DI。
在传统的编程模式中,对象通常会自行实例化依赖的对象,而在IoC模式下,对象的依赖关系由外部容器来管理和维护,对象只需声明其依赖,无需关心具体实现。 Spring通过IoC容器实现了这一模式,该容器负责对象的生命...
传统的编程模式中,对象创建自身依赖的对象并调用它们,而在IoC模式下,对象依赖的其他对象是由外部容器提供的。这样做的目的是为了减少对象间的耦合度,提高代码的可维护性和可测试性。 **控制反转的核心思想**:...
而在IoC模式下,类A不再直接创建类B的实例,而是通过一个外部容器(如IoC容器)来提供类B的实例。这样,类A对类B的依赖被“反转”了,控制权从类A转移给了外部容器。 C#中实现IoC通常使用依赖注入(Dependency ...