
2.1 IoC产生背景
在实际项目设计过程中,接口是一个重要组成元素,不同层之间的操作需要通过接口来调用。利用接口,可以实现子类的隐藏,也可以更好地描述不同层之间的操作标准。Java中要想获得接口对象,需要通过关键字new来实现。
范例:通过关键字new实例化接口对象。

本程序是一个典型的Java原生代码处理操作。new是Java进行对象实例化最基础的关键字,但使用new会暴露IMessage接口子类,同时会让子类与接口之间产生耦合,如图2-1所示。

图2-1 通过关键字new实例化接口对象
很明显,不同层之间出现接口子类暴露是一种不合理的设计模式,因为调用者并不需要知道具体子类是哪个,只需要取得接口对象即可。采用工厂设计模式,就可以起到解耦合的目的。
范例:通过工厂设计模式获取接口对象。

本程序采用工厂设计模式解决了调用者与具体子类之间的耦合关联。调用者只需通过Factory类,就可以获取接口对象,不用再关注具体的子类是哪一个。本程序的代码结构如图2-2所示。

图2-2 通过工厂类获取接口对象
虽然通过工厂设计模式可以改善接口对象的获取处理,但如果一个接口有无数个子类,且这些子类可随时动态增加,这样的静态工厂设计就会产生问题,会导致大量的修改操作。实际开发中,还需要结合反射机制来改善工厂设计。
范例:利用反射机制改善工厂设计。

本程序通过反射机制修改了Factory工厂类的设计,在调用Factory.getInstance()方法时,必须明确传入子类对象的完整名称。这样设计的好处在于,工厂类不会再与某个具体的接口或子类耦合,因此更加具有通用性。本程序的代码结构如图2-3所示。

图2-3 反射与工厂设计相结合
本例利用反射机制成功改良了工厂类的设计,使得程序结构更加清晰,同时避免了程序代码可能产生的耦合问题,但这样的配置依然存在着以下问题:
获取对象时需要传递完整的“包.类”名称。这样的客户端调用显然存在缺陷,最好的解决方案是追加一个配置文件,而后根据某个名称来获取对应的“包.类”名称信息,再通过反射进行加载。
配置文件不应该只简单描述“名称=包.类”关系,还应包含依赖关系配置。
应该更合理地实现多线程管理,避免过多的重复对象产生。
也就是说,要想实现一整套合理的对象管理容器,直接采用原生Java代码并不只靠一个简单的反射机制可以解决问题,还需要考虑各种对象的状态与对象管理。Spring的IoC技术可以帮助开发者减少这些设计上的思考,使其将更多精力放在核心代码的开发处理上。