学到Spring老师一定会讲一句话:IOC能够降低耦合性。可是为什么会降低耦合性,许多老师就讲不清了或者干脆不讲,下面我们通过举一些栗子,一步一步地说明为什么IOC能够降低耦合性。
前言
通过本文你将学习体会到:
- IOC为什么能降低耦合性/IOC为什么能够解耦?
- 面向接口编程相对于面向对象编程有什么好处。
- 工厂模式有什么好处?为什么要费劲巴拉地创造一个
类
去生产对象
,直接new
不挺好的吗? - IOC生产bean的核心理念
第一层-传统方式
通常我们写java程序都是通过实例化来获取对象,代码如下:
Dog dog = new Dog();
dog.bark();
如果我们想要将Dog换成Cat,就需要在所有的程序中将Dog dog = new Dog()
换成Cat cat = new Cat()
.除此之外,cat对象
没有bark
方法,而是具有meow
方法,那么所有程序基本上等于白写了,你需要在所有程序中找到实例化dog对象
的语句,然后将其替换成实例化cat对象
,然后还要找到使用了dog对象
的地方,删除bark
方法的调用,换程meow
方法。也就1000多处声明,1000多处调用,今天和明天加加班就能搞完!!!加油!!!奥里给!!!
而且我们还不能保证替换掉是否会带来其他问题,那需要测试再全用例跑一遍吗?投入非常的大。
第二层-面向接口编程
有个小天才说,我们约定好一些公用的方法,大家都去实现它,不就可以任意切换了吗?对这就是接口.
代码如下:
public interface Animal {
void makeSound();
}
Animal animal = new Dog()
animal.makeSound();
好了现在我想把Dog
换成Cat
,只需要将所有的new Dog()
换成new Cat()
就行了,使用接口最起码减少了bark换程meow方法带来的影响
。只需要在所有的程序中寻找Dog就好.也就如果你有1000个类,只需要今晚加加班就能搞定!!!加油!!!奥里给!!!
实现接口虽然一定程度地降低了耦合程度,但是如果我们实现的类越来越多,对于这些实现类的对象的管理将成为很大的问题,比如我们明天又想实现一个类Fox
,后天想要实现一个Elephent
类,实现类越来越多,越来越难管理。(有的人可能在想什么对象会每天变化呀,博主是不是在纯粹抬杠,哈哈,你想想电商促销,是不是今天给你发一个300-50的券,明天促销方案可能变为9折,还有没有可能变为买1送2)
接口能够一定程度上降低代码的耦合度,接口就像一个插头面板,面板后面可以接火线也可以接零线.正是这个面板,让我们可以在符合标准的线之间任意切换.
第三层-工厂模式
为了提高内聚性,专职类负责特定的事情,所以我们使用一个类作为工厂类,既能生产Dog对象又能生产Cat对象。
代码如下:
class AnimalFactory{
AnimalFactory(){}
public static Animal getInstance(String type){
Animal result = null;
if("dog".equals(type)){
result = new Dog();
}
if("cat".equals(type)){
result = new Cat();
}
return result;
}
}
如果某一天我们又实现了Fox类,那么可以很从容地在AnimalFactory中添加如下代码:(虽然不符合开闭原则,但是相对之前已经很好了)
class AnimalFactory{
AnimalFactory(){}
public static Animal getInstance(String type){
Animal result = null;
if("dog".equals(type)){
result = new Dog();
}
if("cat".equals(type)){
result = new Cat();
}
if("fox".equals(type)) {
result = new Fox();
}
return result;
}
}
Animal animal = AnimalFactory.getInstance("dog");
animal.makeSound();
这种方法把创建对象的过程交给了一个专业的类(Factory),我只需要告诉他我需要什么(参数),他就会返回给我正确的对象,只是解决了内聚性的问题,但是他并没有解决我的声明语句七零八落的散落在程序中,我还是需要去将参数从"dog"
替换为"cat"
但有了替换程序,我只需要裁定一下是否替换,两个小时应该可以搞定,今晚晚下班一会应该可以搞定!!!
第四层-反射
后来又有个大天才,他想到一个更绝妙的主意.我在写程序的时候不告诉工厂我需要什么,等到运行的时候我再告诉工厂我需要什么,你再利用反射技术给我生产出来不就可以了吗?
Animal animal = AnimalFactory.getInstance(我想要的你去config中读取); // 请注意我们使用的是第二层的接口
animal.makeSound();
我想要的 = dog
好了,工厂要生产什么全部都写在了一个文件中,我只需要利用反射技术,在运行时再去读取要工厂生产的东西即可.这样如果我不希望生产dog了,只需要修改配置文件中dog->cat即可,只修改一处就行了.只需30秒,今晚不加班!!!
对于生产对象这件和业务没有直接关系的事情,我们已经提取给了专业的工厂,专业的工厂还是根据配置文件进行的生产,想生产什么我只需要改一处即可,这就是降低了耦合性(生产对象和业务之间的耦合,让生产对象对业务的影响降到了最低)。
利用配置文件+反射技术除了修改方便之外还带来一项好处:我们没有修改任何一处代码,只是改了配置文件,也就是说我们的代码不需要重新编译.
第五层-IOC
在第四层中的AnimalFactory其实是一个专职工厂,其只能生产符合(实现)Animal
接口的类。我们要是能够创造一个什么类型的对象都可以生产的工厂就好了。。。
哈哈,不用创造了,Spring的IOC就是一个这样的工厂呀。
就这样我们一步一步的降低了代码之间的耦合度。
总结
第四层就是IOC在做的事情
IOC = 工厂模式+反射+配置文件读取
工厂模式提高内聚性(创建对象的事情就由专门的类负责),反射+配置文件就是IOC生产bean的法宝。
所有的JavaBean都被IOC的工厂管理,你需要的时候就和工厂说一声我需要XXX就可以了,这样工厂就会返回给你一个正确的对象.在不需要的时候修改工厂的生产列表(配置文件),工厂就停止生产该JavaBean了。
我们一步一步的降低了代码的耦合性,提高了内聚性。
所以说让专业的人干专业的事是社会的进步,社会分工带给我们更多的社会财富!!!
推广
如果你还有什么疑问或者本文帮助到了你,请多多给博主评论呀~也欢迎关注博主,我会一直坚持输出好文的。
连载系列: JVM看这篇就够了
如果你总是看了许许多多的JVM书籍或者视频过段时间就把其中原理忘得一干二净,如果你总是想不能明白此时程序运行时JVM该进行到哪一步了,那就来看看这一篇JVM原理教程吧。这个教程将从JVM的启动运行讲起,让你在每一次点击idea运行按钮时都能想起虚拟机都在干什么,这还怕忘了不成??看完该系列你将获得:
- java编译后的文件内部结构(javac编译)?
- JVM是如何启动的?
- 最先加载的类是什么类?
- 双亲委派机制,为什么要有双亲委派机制?
- 加载后的类去了哪里?
- 我要运行main方法 JVM是如何协同工作的(主要讲解内存)
- 等等。。。。
这些很琐碎的知识点,很多老师都是不讲的,老师通常只会告诉你哪个部分有哪个结构,是干什么的,讲完你真的能知道JVM是如何协同工作的吗?全靠死记硬背,可是JVM真的是一个密不可分的整体呀。如果你真的理解了这个整体是如何高效工作的,你还会怕讲不明白哪个部分是干什么的吗?