Spring 核心思想 之反向控制概念解析(有例子) 博客分类: Spring iocspring反向控制
程序员文章站
2024-03-21 10:18:04
...
“反向控制”的意思书上说很简单,开发人员通常把它理解为“实现必须依赖抽象”或者面向接口编程。这句话对于完全不知道的人来说还是完全不知道。。。想起了两个月前的我
下面我把让我理解了这个概念的例子搬上来,与大家共享下。
这个示例主要讲的是如何通过IOC实现具体的业务逻辑,以及如何向不同的存储位置存储数据,我们可能用到的存储方式有三种:
1.向数据库存储数据(不会在例子中出现)
2.向XML中存储数据
3.向文本文件中存储数据
说明概念的思路是:首先我们介绍编写这类程序通常的做法,然后指出这种做法的不足,接着会给出一种比较好的做法,即通过IOC来实现这类功能,最后对这种做法进行总结,使读者一步一步地了解IOC。
由于是讲解概念,所以我们能省的就省。
首先我们写向XML中存储数据的程序:
通常编写这类程序都是先编写一个向XML存储数据的类XMLData.java,其中saveXML是XMLData类的一个方法,负责向XML存储数据。
//************ XMLData.java *******************//
public class XMLData {
...
//向XML中存储数据
public void saveXML() {
...
}
}
业务逻辑类Business.java 通过 XMlData.java中的方法向XML中存储数据Business.java的示例代码如下:
//************ Business.java *******************//
public class Business {
private XMLData db = new XMLData();
...
//向XML中存储数据
publc void saveData() {
...
db.saveXML();
...
}
}
上面业务逻辑类Business.java和数据存储类XML.java都被设计为实体类,不足之处在于Business类依赖于XML.java类。如果业务改变,用户现在要求向文本文件中存储数据,显然这个时候程序已经不适用了,必须要修改Business类。
我们先修改为向文本文件中存储数据,再来改变Business类。TXTData.java的示例如下。其中saveTXT()是TXTData类中的一个方法,具体负责向文本文件中存储数据。
//************ TXTData.java *******************//
public class TXTData {
...
//向文本文件中存储数据
public void saveTXT() {
...
}
}
然后我们要改向TXT中存储数据,所以就必须得修改业务逻辑类Business.java,改为向TXT中存储数据。Business.java的示例代码变为:
//************ Business.java *******************//
public class Business {
private TXTData db = new TXTData();
...
//向文本文件中存储数据
publc void saveData() {
...
db.saveTXT();
...
}
}
可以看到,这里对业务逻辑类Business的改动比较大,在这里讲解存储方式的改变,目的是让你明白,这是个多么不好的设计方案:因为每次业务需求的变动都要导致程序的大量修改。
下面我们利用IOC来解决这个问题,编写的思路是:首先我们编写一个存储数据的接口,然后每个具体负责存储数据的类都实现这个接口,如前面的XMLData.java,TXTData.java。而在业务逻辑类Business里,则针对存储数据的接口编程,并不与存储数据的类建立任何直接的联系。这样一来的话,存储方式发生任何变化都不糊要修改业务逻辑类Business.java。
1,首先我们来编写个存储数据的接口SaveData,让该接口中定义一个方法saveData()用来负责存储数据,这样一来的话,任何一个具体负责存储数据的类都要实现这个方法,而我们的业务逻辑类只针对接口中的saveDate()方法编程就行.
//************ SaveData.java *******************//
public interface SaveData{
//该方法用来存储数据
public void saveData();
}
2,接下来我们编写个具体负责向XNL存储数据的类XMLData,该类实现了接口SaveData。
//************ XMLData.java *******************//
public class XMLData implement SaveData{
//该方法用来存储数据
public void saveData() {
//以下是具体负责向XML存储数据的代码
...
}
}
3,编写业务逻辑类Business,该类只针对接口SaveData编码,而不是针对实体类。
//************ Business.java *******************//
public class Business {
//针对接口SaveData定义变量
private SaveData db;
public void setSaveData (SaveData db) {
this.db = db;
}
...
//根据注入的存储类,存储数据
public void saveData() {
...
db.saveData();
...
}
}
4,编写测试类Test
//************ Test.java *******************//
public class Test {
private Business business = new Business();
...
//根据注入的存储类,存储数据
public void saveData() {
...
business.setSaveData(new XMLData());
business.saveData();
...
}
}
通过这种方法,Business就可以重用了,不管采用哪种存储方式来存储数据,Business类都不需要改动了,只需要实现具体的SaveData接口就可以了。
5,编写具体负责向文本文件存储数据的类TXTData,该类实现了接口SaveData。TXTData.java的示例代码:
//************ TXTData.java *******************//
public class TXTData implement SaveData{
//该方法用来存储数据
public void saveData() {
//以下是具体负责向文本文件存储数据的代码
...
}
}
6,业务逻辑类Business在这里就不需要做任何的改变,只需要修改测试类Test:
//************ Test.java *******************//
public class Test {
private Business business = new Business();
...
//根据注入的存储类,存储数据
public void saveData() {
...
business.setSaveData(new TXTData());
business.saveData();
...
}
}
这些就是例子的全部了,通过上面我们应该了解到一些“面向接口编程”的好处,它使得业务逻辑代码实现了重用,从而实现了如果不是业务逻辑发生变化,就可以不要修改逻辑的相关代码,这里就是IOC的强大之处。
最后 你可能会有些疑问了:虽然明白了“面向接口编程”的好处,可为什么叫做“反向控制”呢?其实它的意思就是说:原来由业务逻辑来控制具体的存储方式,即业务逻辑里编写具体的存储方式,面向接口后,不在业务逻辑里编写具体的存储方式了,而是在调用业务逻辑的类里来控制具体的存储方式,好像是由具体的存储方式来控制业务逻辑(给你这种感觉),所以把它叫做“反向控制”。
(这篇文章是我看着书本弄出来的,所以不能标原创了, 网上好像缺少这种比较具体的,至少我当时在网上找了很久都没有找到我想要的这种)
首先把这篇文章写给以前惶惶然的自己,写给需要的朋友们,有什么错误可以在评论里提醒下,万分感谢 远方的朋友
下面我把让我理解了这个概念的例子搬上来,与大家共享下。
这个示例主要讲的是如何通过IOC实现具体的业务逻辑,以及如何向不同的存储位置存储数据,我们可能用到的存储方式有三种:
1.向数据库存储数据(不会在例子中出现)
2.向XML中存储数据
3.向文本文件中存储数据
说明概念的思路是:首先我们介绍编写这类程序通常的做法,然后指出这种做法的不足,接着会给出一种比较好的做法,即通过IOC来实现这类功能,最后对这种做法进行总结,使读者一步一步地了解IOC。
由于是讲解概念,所以我们能省的就省。
首先我们写向XML中存储数据的程序:
通常编写这类程序都是先编写一个向XML存储数据的类XMLData.java,其中saveXML是XMLData类的一个方法,负责向XML存储数据。
//************ XMLData.java *******************//
public class XMLData {
...
//向XML中存储数据
public void saveXML() {
...
}
}
业务逻辑类Business.java 通过 XMlData.java中的方法向XML中存储数据Business.java的示例代码如下:
//************ Business.java *******************//
public class Business {
private XMLData db = new XMLData();
...
//向XML中存储数据
publc void saveData() {
...
db.saveXML();
...
}
}
上面业务逻辑类Business.java和数据存储类XML.java都被设计为实体类,不足之处在于Business类依赖于XML.java类。如果业务改变,用户现在要求向文本文件中存储数据,显然这个时候程序已经不适用了,必须要修改Business类。
我们先修改为向文本文件中存储数据,再来改变Business类。TXTData.java的示例如下。其中saveTXT()是TXTData类中的一个方法,具体负责向文本文件中存储数据。
//************ TXTData.java *******************//
public class TXTData {
...
//向文本文件中存储数据
public void saveTXT() {
...
}
}
然后我们要改向TXT中存储数据,所以就必须得修改业务逻辑类Business.java,改为向TXT中存储数据。Business.java的示例代码变为:
//************ Business.java *******************//
public class Business {
private TXTData db = new TXTData();
...
//向文本文件中存储数据
publc void saveData() {
...
db.saveTXT();
...
}
}
可以看到,这里对业务逻辑类Business的改动比较大,在这里讲解存储方式的改变,目的是让你明白,这是个多么不好的设计方案:因为每次业务需求的变动都要导致程序的大量修改。
下面我们利用IOC来解决这个问题,编写的思路是:首先我们编写一个存储数据的接口,然后每个具体负责存储数据的类都实现这个接口,如前面的XMLData.java,TXTData.java。而在业务逻辑类Business里,则针对存储数据的接口编程,并不与存储数据的类建立任何直接的联系。这样一来的话,存储方式发生任何变化都不糊要修改业务逻辑类Business.java。
1,首先我们来编写个存储数据的接口SaveData,让该接口中定义一个方法saveData()用来负责存储数据,这样一来的话,任何一个具体负责存储数据的类都要实现这个方法,而我们的业务逻辑类只针对接口中的saveDate()方法编程就行.
//************ SaveData.java *******************//
public interface SaveData{
//该方法用来存储数据
public void saveData();
}
2,接下来我们编写个具体负责向XNL存储数据的类XMLData,该类实现了接口SaveData。
//************ XMLData.java *******************//
public class XMLData implement SaveData{
//该方法用来存储数据
public void saveData() {
//以下是具体负责向XML存储数据的代码
...
}
}
3,编写业务逻辑类Business,该类只针对接口SaveData编码,而不是针对实体类。
//************ Business.java *******************//
public class Business {
//针对接口SaveData定义变量
private SaveData db;
public void setSaveData (SaveData db) {
this.db = db;
}
...
//根据注入的存储类,存储数据
public void saveData() {
...
db.saveData();
...
}
}
4,编写测试类Test
//************ Test.java *******************//
public class Test {
private Business business = new Business();
...
//根据注入的存储类,存储数据
public void saveData() {
...
business.setSaveData(new XMLData());
business.saveData();
...
}
}
通过这种方法,Business就可以重用了,不管采用哪种存储方式来存储数据,Business类都不需要改动了,只需要实现具体的SaveData接口就可以了。
5,编写具体负责向文本文件存储数据的类TXTData,该类实现了接口SaveData。TXTData.java的示例代码:
//************ TXTData.java *******************//
public class TXTData implement SaveData{
//该方法用来存储数据
public void saveData() {
//以下是具体负责向文本文件存储数据的代码
...
}
}
6,业务逻辑类Business在这里就不需要做任何的改变,只需要修改测试类Test:
//************ Test.java *******************//
public class Test {
private Business business = new Business();
...
//根据注入的存储类,存储数据
public void saveData() {
...
business.setSaveData(new TXTData());
business.saveData();
...
}
}
这些就是例子的全部了,通过上面我们应该了解到一些“面向接口编程”的好处,它使得业务逻辑代码实现了重用,从而实现了如果不是业务逻辑发生变化,就可以不要修改逻辑的相关代码,这里就是IOC的强大之处。
最后 你可能会有些疑问了:虽然明白了“面向接口编程”的好处,可为什么叫做“反向控制”呢?其实它的意思就是说:原来由业务逻辑来控制具体的存储方式,即业务逻辑里编写具体的存储方式,面向接口后,不在业务逻辑里编写具体的存储方式了,而是在调用业务逻辑的类里来控制具体的存储方式,好像是由具体的存储方式来控制业务逻辑(给你这种感觉),所以把它叫做“反向控制”。
(这篇文章是我看着书本弄出来的,所以不能标原创了, 网上好像缺少这种比较具体的,至少我当时在网上找了很久都没有找到我想要的这种)
首先把这篇文章写给以前惶惶然的自己,写给需要的朋友们,有什么错误可以在评论里提醒下,万分感谢 远方的朋友
上一篇: 内联函数与宏定义
下一篇: C++中内联函数和宏定义