演进式例解控制反转(IoC)、依赖注入(DI)之一
原创作品,允许转载,转载时请务必以超链接形式标明文章
原始出处 、作者信息和本声明。否则将追究法律责任。
http://www.voidcn.com/article/p-qufjpzul-bs.html
?近来总是接触到 IoC(Inversion of Control,控制反转)、DI(Dependency Injection,依赖注入)等编程原则或者模式,而这些是著名 Java框架 Spring、Struts等的核心所在。针对此查了 Wikipedia中各个条目,并从图书馆借来相关书籍,阅读后有些理解,现结合书中的讲解以及自己的加工整理如下:
?
问题描述:
开发一个能够按照不同要求生成Excel或 PDF格式的报表的系统,例如日报表、月报表等等。
?
解决方案:
根据“面向接口编程”的原则,应该分离接口与实现,即将生成报表的功能提取为一个通用接口ReportGenerator,并提供生成 Excel和 PDF格式报表的两个实现类 ExcelGenerator和 PDFGenerator,而客户Client再通过服务提供者 ReportService获取相应的报表打印功能。
?
实现方法:
根据上面所述,得到如下类图:
?
代码实现:
?
?
?
问题描述:
如上面代码中的注释所示,具体的报表生成器由 ReportService类内部硬编码创建,由此 ReportService已经直接依赖于 PDFGenerator或 ExcelGenerator,必须消除这一明显的紧耦合关系。
?
解决方案:引入容器
引入一个中间管理者,也就是容器(Container),由其统一管理报表系统所涉及的对象(在这里是组件,我们将其称为 Bean),包括 ReportService和各个 XXGenerator。在这里使用一个键-值对形式的 HashMap实例来保存这些 Bean。
?
实现方法:
得到类图如下:
?
代码实现:
?
时序图大致如下:
?
效果:
如上面所示,ReportService不再与具体的 ReportGenerator直接关联,已经用容器将接口和实现隔离开来了,提高了系统组件 Bean的重用性,此时还可以使用配置文件在 Container中实时获取具体组件的定义。
?
?
问题描述:
然而,观察上面的类图,很容易发现 ReportService与 Container之间存在双向关联,彼此互相有依赖关系。并且,如果想要重用 ReportService,由于它也是直接依赖于单独一个 Container的具体查找逻辑。若其他容器具体不同的组件查找机制(如 JNDI),此时重用 ReportService意味着需要修改 Container的内部查找逻辑。
?
解决方案:引入 Service Locator(最终未用此法)
再次引入一个间接层 Service Locator,用于提供组件查找逻辑的接口,请看Wikipedia中的描述或者 Java EE对其的描述1、描述2。这样就能够将可能变化的点隔离开来。
?
实现方法:
类图如下:
?
代码实现:
?
小结: 1、虽然讲了这么大篇幅还没有进入真正的主题——IoC、DI,不过已经在一步步逼近了,下一篇应该会更精彩!在这里... 2、可以很明显地看得出上面两中重新设计以解耦、隔离变化点都是通过引入间接层得以解决的。 3、在看书过程中,我感觉《Spring攻略》一书中以“问题描述、解决方案、实现方法”方式的讲解比较容易理解和理清思路,故而也学习用这种方式来写。另,推荐该书以学习 Spring框架(尽管目前我看得也不多)。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |