我们为什么需要IoC框架
你今天被“皇马”了吗?假如你是那个写“皇马”程序的程序猿,你是否想让你讨厌的人变成“皇马”?于是你开始用代码来施展你的魔法,写下如下咒语:
class SomeBodyYouHate
{
private String name;
private boolean isYellowHorse;
public boolean isYellowHorse()
{
return isYellowHorse;
}
public String getName()
{
return name;
}
public String setName(String name)
{
this.name=name;
}
void letYouYellowHorse(boolean isYellowHorse)
{
this.isYellowHorse=isYellowHorse
}
}
class YellowHorseApp
{
public static void main(String[] args)
{
magic();
}
static void magic()
{
SomeBodyYouHate s=new SomeBodyYouHate();
s.setName("xxx");
s.letYouYellowHorse(true);
}
}
写完上面的咒语,你开始启动程序,咒语生效了。但是有一天你的老板对你说,你这样做是不对的,老板对你晓之以情,动之以理,本性善良的你于是回心转意,想要将程序用于正道,但是你发现:完蛋了,又要改代码,程序需要重新编译运行,不然真的玩不转了!
言归正传,以上代码你有没有发现以下问题?
- 代码强依赖于SomeBodyYourHate,无法进行灵活替换
- 代码比较low,为了使用SomeBodyYourHate,我们需要做一些初始准备,比如:需要对SomeBodyYourHate初始化,设置一些名称等。
你很努力,后来你学习了各种设计模式,于是你发现好像工厂模式可以解决上面的问题,于是你用工厂模式改了一下上面的代码:
interface IYellowHorse
{
void letYouYellowHorse(boolean isYellowHorse);
}
class SomeBodyYouHate implements IYellowHorse
{
...
}
class SomeBoyNeedToBeYellow implements IYellowHorse
{
...
}
class YellowHorseFactory
{
static void IYellowHorse createYellowHorsePerson(String name)
{
// 此处可以采用配置方式创建对象,为避免复杂性,这里直接创建需要变“皇马”的对象
return new SomeBoyNeedToBeYellow(name);
}
}
class YellowHorseApp
{
public static void main(String[] args)
{
magic();
}
static void magic()
{
IYellowHorse s= YellowHorseFactory.createYellowHorsePerson("xxx");
s.letYouYellowHorse(true);
}
}
当你沾沾自喜时,你的老板对你的代码指出了下面几个问题:
- 虽然你赶走了一批狼(强依赖于SomeBodyYourHate),但是又来了一匹虎(强依赖于YellowHorseFactory)
- YellowHorseFactory不便于进行单元测试,我们都知道,单元测试需要mock对象,如果使用了YellowHorseFactory我们构造mock对象并传入,这样就违背了开闭原则,因为我们需要从传入构造好的对象。
那么,有没有更好的方式呢?
当然有,马丁.福勒大师提出了IoC的概念,IoC的全称叫做控制翻转(Inversion of Control),其核心思想是“耍大牌”的“好莱坞原则”,即你不要给我打电话,我打给你,用业内的话来说就是“最小依赖原则”,对象不需要知道外部任何细节,什么用,在哪里用,完全由外部来决定。
为什么我们需要IoC框架
俗话说,一个不会偷懒的程序猿不是一个好的程序猿。我们习惯于只关注于自己的核心业务,对于一些边边角角的事情会导致分散我们的注意力,如果处理不当还有可能导致各种“事故”。所以我们应该习惯于让各种“框架”帮我们做事情,一个好的框架可以让开发变得事半功倍,同时让我们的程序变得更“整洁”,同时又不容易出错,有时会获得更好的性能。
IoC框架的核心在于它能更好的管理好对象实例,特别是能让对象实例进行复用,我们不用在意对象创建的任何细节,同时当我们需要时可以随意对对象进行修改和扩展而不需要对类进行修改,完全满足了开闭原则。
市场上主流的IoC框架有Spring,Guice等,众所周知,这些框架为大多数厂商使用,作为一个工具它其实不带任何的主观色彩,完全在于使用的人以及使用的场景,存在即合理,我们需要正视IoC框架对程序开发以及维护重要性,下节我们将介绍如何设计一个IoC框架。
如何设计一个IoC框架
在上面的例子中,工厂模式其实为IoC框架如何实现提供了思路,工厂是一个显示的管理对象的容器,但是他比较简陋,没有缓存,每个对象每次调用都要重复创建,同时无法决定我们的对象以何种方式创建:单例或者原型。为了克服工厂的局限性,我们来说说一个合格的IoC应该具备什么特征:
- 简洁的依赖配置方式。
- 具备基本的对象缓存。
- 需要能提供单例或者原型方式。
- 方便对对象的创建过程进行干预和扩展。
- 具备基本的AOP扩展能力。
- 可以让用户定义工厂进行创建对象。
如果你热衷于造轮子的话我建议你从Spring框架的源代码开始看起,但是如果是喜欢更轻量级的框架的话,我建议你使用Guice,其实我这个人不太喜欢造轮子,因为你的轮子造的再好也很难超越经典的开源框架,但是造轮子对于我们个人对开源框架的学习还是有帮助的。对于企业应用我还是推荐使用第三方开源的框架,因为使用开源框架有如下几个好处:
- 降低用人成本,使用开源框架的人才较多,不用单独进行培训和学习
- 开源团队有较强的实力,可以保证产品的更新迭代,而不用担心功能受限和安全问题
- 开源框架有较好的生态,有完善的文档,可以大大缩短产品开发的生命周期
- 开源框架保持较好的向前兼容性,同时如果企业参与开源框架可以提高自身的知名度。