java学习之依赖注入、控制翻转
这两天学了反射,首先了解面向对象思想,对一个整体进行分割,体会为‘类’,最终完成的项目由类构成,类是最小的组织单位。类与类如何产生协作?是通过内部通信,即‘调用’来实现的。类与类之间的关系,有组成关系、依赖关系等等。。。类是具体的,接口是抽象的。利用java的语言特性(抽象)----函数是完整有形的,而接口的函数只是一个定义(无形)。
利用接口,我们解决了一半的问题。当两个类产生依赖关系的时候,就会相会影响,但是又不能完全没有关系,完全没有关系是无法进行协作的。因此,就适当的处理它们的关系。类与类之间要相互作用,必须进行通信,而通信就是耦合,耦合产生力的传动。比如在机械学中,两个齿轮,只有咬合在一起,才能传动。也就是说,两个类只有耦合才能协作,那么如果完全没有耦合,就无法协作。所以适当的解耦,才能达到最好的效果。适当的解耦,也叫“松耦合”并不是“零耦合”。
另外一部分是无法通过语言特性来解决问题的,而要通过设计方法来解决。用工厂模式来解决另一半问题,首先解剖问题。
Test1亲自去new TestImpl(),这就控制权,它决定了自己需要什么对象。反过来,当一个类能决定自己需要的具体对象,就说它具有控制权。现在要剥夺它的控制权,交给第三方(工厂)来做获取具体对象。第三方就是工厂。控制权与依赖是双身关系,有控制权,就有依赖。
t2这个对象,被成为依赖件,将获取到的依赖件传入到具体对象中,成为依赖注入。当工厂设计模式完成之后,检查标准是:不论需求如何变更,除了工厂类报错,其它类都不允许报错,那么之后解决工厂类的报错,就一切问题都解决了。
硬编码,出现的具体值,当.java被编译成.class以后,再修改是不可能的,如果要修改,那么之前的class就作废了。那就面临了重新编译。那么,可以改成资源文件-->.java源文件-->.class字节码文件,就可以解决另一半的问题。
Class和.class:
Class抽象了.class文件。所属的包在哪儿?类名是什么?是否有接口?有没有公开构造函数?有没有其它的函数?等等一系列我们在类文件中看到的,都有相关的抽象。
java语言是具有动态特性的就是能在运行的时候进行加载工作,“运行的时候”运行时(Runtime)在程序运行时加载的就叫动态加载。
Object类型抹除(不包含任何类型信息了或者也可以说类型丢失,向上转型)。
以下展示代码:
package com.zhaohuan.java2; public class Test { private Test2 t2; //依赖件 public void setT2(Test2 t2) { //控制权转移出去之后,通过该函数与控制权持有方进行通信,从而获取具体对象 this.t2 = t2; //依赖窗口,通过它从外界获取具体依赖件 } public void temp() { /* Test2Impl t2 = new Test2Impl(); //因为持有控制权,而产生了耦合,应该控制权(这个思想被称为:控制翻转IoC) t2.close();*/ if(t2 != null) { Test2 t = t2; //消除了所有错误,1、利用接口消除了参考类型的依赖 //2、利用控制反转,消除匿名对象的依赖 t.close(); } } }
package com.zhaohuan.java2; public interface Test2 { public void close(); }
package com.zhaohuan.java2; public class Test3Impl implements Test2 { @Override public void close() { System.out.println("安全关闭"); } }
package com.zhaohuan.java2; import java.util.ResourceBundle; public class MyFactory { private static ResourceBundle rb; static { rb=ResourceBundle.getBundle("my"); } /*private static Object getDependency(String className)throws ClassNotFoundException, InstantiationException, IllegalAccessException { String dependency=rb.getString(className); Class clazz=Class.forName(dependency); Object obj=clazz.newInstance(); return obj; } public static Test2 inverse() throws ClassNotFoundException, InstantiationException, IllegalAccessException { Test3Impl t3=(Test3Impl) getDependency("Test3Impl"); return t3; }*/ public static Object getDependency(String className)throws ClassNotFoundException, InstantiationException, IllegalAccessException { String dependency=rb.getString(className); Class clazz=Class.forName(dependency); Object obj=clazz.newInstance(); return obj; } }
package com.zhaohuan.java2; import com.zhaohuan.java2.MyFactory; public class Demo { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Test2 t2=(Test2) MyFactory.getDependency("Test3Impl"); Test t = new Test(); t.setT2(t2); //fc.inverse()返回了依赖件,然后将依赖件传递给test的对象, //因为test对象需要用来test2的对象,所以test2是test的依赖件 //那么我们这种将依赖件传递给需要的对象的做法,就叫依赖(件)注入 t.temp(); } }