星期四, 四月 26, 2007

从简单实例了解Spring的控制反转IoC(Inversion of Control)

Spring 的核心是IoC,而IoC模式也只是一种思想,很早以前就有了“依赖倒转原则”和“面向抽象编程”,就像Hibernate的ORM思想一样,重要的是学习人家怎么把思想应用到开发上,或框架上上。这样的设计,又一次地把解耦合的思想灌述进来,实在是很精彩的思想。 这里还是让大家从实例来了解和分享IoC把。
以对象导向的方式来设计,依赖反转(Dependency Inversion)的解释为“程序不应该依赖实现,而是依赖于抽象接口”。看以下程序:





public class Business{
private FloppyWrite writer= new
FloppyWriter();
...
public void save()
{
...
writer.saveToFloppy();
}

}



Business类的设计中,存盘的需求依赖于实际的FloppyWrite对象,若想要将存储介质改为USB磁盘,则必须修改Business的程序,无法重用Business类。
通过接口这样申明一个接口:





public interface IDeviceWriter{
public void saveToDevice()
{
}

}



那么Business类可以这样设计了,遇到存盘时,将其依赖于IDeviceWriter接口,而不是依赖于实际的FloppyWriter这个实现:





public class Business{
private
IDeviceWriter;

public void setDeviceWriter(IDeviceWriter writer)
{
this.writer=
writer;
}

public void save(){
...
writer.saveToDevice();
}

}




这样的设计Business类就可以重用了,倘若要存储至Floppy或USB磁盘,这只需要针对这两种需求分别实现接口即可:
针对Floppy存储设计一个FloppyWriter类:




public class FloppyWriter implement IDeviceWriter{
public void saveToDevice()
{
...
//实际存储至Floppy的代码

}

}



或针对USB磁盘存储设计一个UsbDiskWriter类:




public class UsbDiskWriter implement IDeviceWriter{
public void saveToDevice()
{
...
//实际存储至Floppy的代码

}

}



这样的话,采用USB磁盘存储只需编写一个配置程序如下:
Business business= new Business();
business.setDeviceWriter(new UsbDiskWriter());
business.save();
而Spring融入这个思想的同时,还将选择实现的配置写入XML,这样更改配置更加方便。


现在再来理解下Dependency Inversion的解释:“程序不应该依赖实现,而是程序和实现都要依赖于抽象接口”。
在Martin Fowler的文章中也谈过Dependency Injection(依赖注入),其分三种实现方式:Interface injection,Setter injection(setter方法注入),Constructor injection(构造时注入)。而这里用到的是 Setter方式,也是Spring鼓励的方式。


是不是已经理解了,是不是感觉心里的特别的舒畅,我也是这样的,很高兴跟大家分享我领悟的!

现在来看这张图片,进行J2EE开发中的DAO设计时应用上这种依赖关系,不用多说了,图片已经把这种关系解释得很微妙了。

1 条评论:

匿名 说...

I should email my friend about this.