IoC容器的核心原理与机制

IoC是个通用的设计机制,DI(依赖注入)则是具体的设计模式,它体现了IoC的设计原则。DI是IoC的最典型的实现,因此术语上IoC和DI经常混淆使用。

     面向对象设计的基本思想是将系统分解为一组可重用的对象。如果没有一个核心模块来管理这些对象,它们将不得不各自创建和管理自己的依赖。结果就是这些对象会紧紧地耦合在一起。解决的方法就是,提供一个容器来管理组成系统的对象。该容器集中创建对象,并以注册表的形式提供对象的查找服务。同时,它还管理对象的生命周期,并为这些对象提供一个运行平台。运行于容器的对象必须遵循容器所定义的规范。

1、假设现在要实现打印报表这个功能,打印报表可生成Html和Pdf格式等不同类型。根据面向对象设计的“接口与实现分离”的原则,类图如下:

 

View Code
//接口ReportG
public interface ReportG {

    public void getReport();
}

//HtmlReport类
public class HtmlReport implements ReportG {

    @Override
    public void getReport() {
        // TODO Auto-generated method stub
        //do something
    }

}

//PdfReport类
public class PdfReport implements ReportG {

    @Override
    public void getReport() {
        // TODO Auto-generated method stub
        //do something
    }

}

//ReportService类
public class ReportService {

    private ReportG report = new HtmlReport();  //耦合
    
    public void remove()
    {
        report.getReport();
        //...        
    }    
    public void display()
    {
        report.getReport();
        //....
    }
}

 

2,采用容器

类图修改为:

View Code
//Contain类

import java.util.HashMap;
import java.util.Map;

public class Contain {

    public static Contain instance;
    
    private Map<String,Object> comps; //装入组件的容器
    public Contain()
    {
        instance = this;
        comps = new HashMap<String,Object>();
        
        //依次装入
        ReportG ht = new HtmlReport();
        comps.put("htmlReport", ht);
        
        ReportG pdf = new PdfReport();
        comps.put("pdfReport", pdf);
        
        ReportService rs = new ReportService();
        comps.put("reportService", rs);        
    }
    
    public Object getComponent(String id)
    {
        return comps.get(id);        
    }
}

//修改ReportService类

public class ReportService {

    private ReportG report = (ReportG)Contain.instance.getComponent("htmlReport");
    
    public void remove()
    {
        report.getReport();
        //...
        
    }
    
    public void display()
    {
        report.getReport();
        //....
    }
}

3、在ReportService类中是直接查询ReportG的,可以将查询的部分封装,这样能增加组件的重用性以及降低查询复杂性。
类图修改为:

View Code
//ServiceLocate类
public class ServiceLocate {

    private static Contain contain = Contain.instance;
    public Object getReportG(String id)
    {
        return contain.getComponent(id);
    }
}

4、应用控制反转和依赖注入

传统的资源查找方式要求组件向容器发起请求来查找资源,作为回应,容器适时的返回资源。而应用IoC后,则是容器主动地将资源推送到它所管理的组件里,组件要做的就是选择一种合适的方式来接受资源。

View Code
//修改Contain类
import java.util.HashMap;
import java.util.Map;

public class Contain {
        
    private Map<String,Object> comps; //装入组件的容器
    public Contain()
    {        
        comps = new HashMap<String,Object>();
        
        ReportG ht = new HtmlReport();        
        
        ReportService rs = new ReportService();
        
        rs.setReportG(ht);
        
        comps.put("rs", rs);
    }
    
    public Object getComponent(String id)
    {
        return comps.get(id);        
    }
}

//修改ReportService类

public class ReportService {

    private ReportG report;
    public void setReportG(ReportG report)
    {
        this.report = report;
    }
    
    public void remove()
    {
        report.getReport();
        //...
        
    }
    
    public void display()
    {
        report.getReport();
        //....
    }
}

除了用set方法,叫做setter注入,还可以构造器注入,就是在ReportService的构造器中写入setReportG方法中的代码。

 

 

 

 

posted @ 2013-03-13 22:56  爱生活者wmmang  Views(681)  Comments(0Edit  收藏  举报