面向对象设计的基本思想是将系统分解为一组可重用的对象,但如果没有一个核心模块来管理这些对象的话,它们将不得不各自去创建和管理自己的依赖,而这样的设计原则将使得这些对象变得紧紧的耦合在一起。
对此,我们需要一个容器来管理这些系统对象,同时我们又不希望这个容器像EJB2.*版本时那样的复杂且笨拙,它应该做到足够的轻量。而我们需要在其中创建对象,并且对于使用者来说要提供类似于注册表式的键值方式查找服务,同时这个容器还应该具有管理对象的生命周期,为他们提供运行平台等等一些列功能。系统对象将成为这个容器中的一个个组件,它们的定义则应当严格遵守这个容器锁定下的规则。下面我们将以一些列的简单实现来体现一下我们的想法。
首先我们假设要开发一个报表系统。根据“接口与实现相分离”的设计原则,我们可以对这个实现的借口做如下简单定义:
package com.demo.springdemo.report.generator.interf;
public interface ReportGenerator {
public void generate(String[][] table);
}
而在此我们假设这个接口有两个简单实现,其中的print语句只是简单的告诉我们代码什么时候被执行了。
package com.demo.springdemo.report.generator.impl;
import com.demo.springdemo.report.generator.interf.ReportGenerator;
public class HtmlReportGenerator implements ReportGenerator{
@Override
public void generate(String[][] table) {
System.out.println("Generate HTML report ...");
}
}
package com.demo.springdemo.report.generator.impl;
import com.demo.springdemo.report.generator.interf.ReportGenerator;
public class PdfReportGenerator implements ReportGenerator{
@Override
public void generate(String[][] table) {
System.out.println("Generate PDF report ...");
}
}
同样,我们提供了一个Service来为用户提供具体的打印服务。
package com.demo.springdemo.report.service;
import com.demo.springdemo.report.generator.interf.ReportGenerator;
public class ReportService{
private ReportGenerator reportGenerator = new PdfReportGenerator ();
public void setReportGenerator(ReportGenerator reportGenerator) {
this.reportGenerator = reportGenerator;
}
public void generateAnnualReport(int year) {
String[][] statistics = null;
/**
* 省略实现
*/
reportGenerator.generate(statistics);
}
public void generateMonthlyReport(int year, int month) {
String[][] statistics = null;
/**
* 省略实现
*/
reportGenerator.generate(statistics);
}
public void generateDailyReport(int year, int month, int day) {
String[][] statistics = null;
/**
* 省略实现
*/
reportGenerator.generate(statistics);
}
}
现在,由于ReportService是在内部创建的ReportGenerator 实例,所以它必须要知道将要使用的是哪一个具体ReportGenerator 实现类,这也就导致了ReportService对于ReportGenerator 实现类的直接依赖关系,而这个时候我们则可以通过一个容器来消除这种直接的依赖关系。假设容器实现如下:
package com.demo.springdemo;
...
public class Container{
public static Container instance;
private Map<String,Object> components;
public Container (){
components = new HashMap<String,Object>();
instance = this;
ReportGenator reportGenerator = new PdfReportGenerator();
components.put("reportGenerator ",reportGenerator );
ReportService reportService = new ReportService ();
components.put("reportService ",reportService );
}
public Object getComponent(String id) {
return components.get(id);
}
}
在这个简单的容器实现中,我们以Map形式来存储了各个组件。在容器的初始化过程中,把各个组件放入了Map中,以便于接下来的使用,并且提供了通过组建ID进行组建查找的获取方式。而在这当中,我们还利用了静态公共变量instance来存储容器的全局公共实例。至此,我们可以对于ReportService服务类做如下修改,
package com.demo.springdemo.report.service;
...
public class ReportService{
private ReportGenerator reportGenerator = (ReportGenerator)Container.instance.getComponent("reportGenerator ");
...
}
这个看似简单的修改也就意味着我们取消了ReportService对于ReportGenerator 具体实现的依赖关系,而当我们更换ReportGenerator 的具体实现的时候不许要在更改ReportService类了,而只需要为不同的需求来配置不同的容器实现即可,这也使得ReportService较之以前拥有了一定的重用性,但同时也使得ReportService对于容器产生了依赖关系,着同样也是个不怎么好的信号,问题如斯,尚待后面解决。
简单的测试一下吧。
package com.demo;
import com.demo.springdemo.Container;
import com.demo.springdemo.report.service.ReportService;
public class Main {
public static void main(String[] args) {
Container container = new Container();
ReportService reportService = (ReportService) container
.getComponent("reportService");
reportService.generateAnnualReport(2009);
}
}
如果看到了控制台打印出Generate PDF report ...,恭喜呢,成功了。
纵观之上我们所做的一切,我们都做了些什么呢?做了个容器,然后简单的将配置从编程逻辑里面分离了出来,而这个看似简单的分离则减少了系统中不同组件之间的耦合度,也提高了各个组件的独立性和重用性,有待提高,继续学习,继感悟~~~
分享到:
相关推荐
PicoContainer 是一个轻量级的Java容器框架,它提供了一种简洁的方式来管理对象及其依赖关系。 **PicoContainer实现代码** ```java DefaultPicoContainer container = new DefaultPicoContainer(); container....
总结来说,IOC容器是通过控制反转来解耦代码的关键组件。虽然这个简单的实现可能无法满足复杂的生产需求,但它足以帮助我们理解DI的核心思想。Spring的IOC容器在这一基础上进行了大量的扩展和优化,使得我们可以轻松...
而控制反转则是将这种控制权交给外部容器(如Spring的IoC容器),由容器来负责实例化、配置和管理组件之间的关系。 ##### 2.2 依赖注入的实现方式 依赖注入(Dependency Injection,DI)是实现控制反转的一种常用...
Castle项目提供了一个强大的IOC容器——Windsor,它建立在MicroKernel之上,能够自动检测和理解类及其依赖关系,从而实现服务的注册、解析和生命周期管理。Windsor不仅可以帮助开发者解决依赖问题,还提供了异常处理...
【自定义IOC容器】是一个Java开发中的实践项目,旨在深入理解Spring框架的核心组件——IOC(Inversion of Control,控制反转)容器的工作原理。IOC容器是Spring框架的核心,它负责管理和装配应用中的对象,实现了...
Java 示例版 Java 社群近来掀起了一阵轻量级容器的热潮,这些容器能够帮助开发者将来自不同项目的组件 ...不过,这两者之间的差异并不太重要,更重要的是:应该将组件的配置与使用 分离开——两个模式的目标都是这个。
【SSH进阶之路】一步步重构容器实现Spring的IoC——解决容器对组件的“侵入式”管理的两种方案--服务定位器和IoC容器(九) 【SSH进阶之路】一步步重构容器实现Spring的IoC——工厂+反射+配置文件实现IoC容器(十)
Spring IoC容器通过XML配置文件或注解来管理对象及其依赖。XML配置文件中定义了bean的定义,包括类名、属性等,而注解如@Autowired则可以自动匹配和注入依赖。Spring容器通过反射机制实例化对象,解析并注入依赖。...
Spring IoC容器在装配Bean时还可以应用生命周期回调,例如实现InitializingBean和DisposableBean接口,或者使用@PostConstruct和@PreDestroy注解,可以在Bean的生命周期的特定点执行代码。 除了上述提到的装配方式...
标题 "Spring3.1.3 Ioc在Web容器中的建立" 涉及的是Spring框架的一个关键特性——依赖注入(Dependency Injection,简称DI),以及如何在Web应用环境中配置和使用它。Spring是Java开发中最流行的轻量级框架之一,...
在“Spring基础:IoC容器(1)”这个主题中,我们将深入探讨Spring的核心组件——IoC容器,以及它如何管理对象的生命周期和依赖关系。 IoC(Inversion of Control),也称为控制反转,是一种设计模式,它将对象的创建...
无论是在XML配置还是注解配置下,开发者都能够轻松地管理应用程序的组件,并且得益于IoC容器的生命周期管理,可以更加专注于业务逻辑的实现。在实际项目中,结合使用Spring的其他功能,如AOP(面向切面编程)、数据...
3. 构建IOC容器:设计一个容器来管理对象的生命周期和依赖关系。实现依赖注入,可以通过构造函数注入、setter注入或接口注入等方式。 4. 整合上述组件:将ORM集成到MVC框架中,使模型能够通过ORM与数据库交互;同时...
同时,他还提到了另一种常见的模式——“服务定位器”(Service Locator),但指出两者的主要区别在于依赖注入模式更倾向于将组件的配置与使用分离,而服务定位器则可能在一定程度上违反了这一原则,因为它允许对象...
IOC容器是实现这一理念的关键,它负责管理应用中的所有对象,根据配置文件或注解自动装配对象间的依赖关系。 在Spring MVC中,四大组件——模型(Model)、视图(View)、控制器(Controller)和存储转发...
3. **配置IoC容器**:使用IoC容器配置组件之间的依赖关系,而不是在组件内部直接管理依赖。 4. **依赖注入**:通过IoC容器在运行时自动注入依赖项。 #### 重构示例 以文中提到的云南铜业集团物流管理系统为例,该...
总结来说,这个例子展示了如何在C#项目中使用Unity实现IOC模式,通过依赖注入来管理对象间的依赖关系,提高代码的灵活性和可维护性。通过分析UnityDemo.sln、UnityDemoApp、FileOperate、FileManager等文件和目录,...
对于Spring的使用者而言,IOC容器不仅是管理Bean(即应用中的对象实例)生命周期的中心,同时也是实现依赖注入(Dependency Injection,DI)的关键所在。在Spring框架中,IOC容器扮演着至关重要的角色,它负责管理...
Martin Fowler的Inversion of Control Containers and the Dependency Injection pattern。...不过,这两者之间的差异并不太重要,更重要的是:应该将组件的配置与使用分离开——两个模式的目标都是这个。
- **配置元数据**:使用XML格式来描述Bean的定义及其依赖关系,Spring IoC容器会根据这些元数据创建和管理Bean。 ##### 2.2 ApplicationContext详解 - **功能增强**:除了提供BeanFactory的所有功能之外,还支持更...