反射 实现工厂模式 和 spring IOC 实现原理

时间:2021-05-26 19:42:18

下面的程序是从魔乐科技java教程里面抄来的,感觉这几段程序说明了一些问题,所以就抄过来了。

下面是一个简单的工厂模式 

[java]  view plain copy
  1. package org;  
  2.   
  3. interface Fruit{  
  4.     public void eat();  
  5. }  
  6. class Apple implements Fruit{  
  7.     public void eat(){  
  8.         System.out.println("吃苹果。");  
  9.     }  
  10. }  
  11. class Orange implements Fruit{  
  12.     public void eat(){  
  13.         System.out.println("吃橘子");  
  14.     }  
  15. }  
  16. class Factory{     //工厂类  
  17.     public static Fruit getInstance(String className){  
  18.         Fruit f=null;  
  19.         if(className.equals("apple")){  
  20.             f=new Apple();  
  21.         }  
  22.         if(className.endsWith("orange")){  
  23.             f=new Orange();  
  24.         }  
  25.         return f;  
  26.     }  
  27. }  
  28. public class FactoryDemo02 {  
  29.     public static void main(String args[]){  
  30.     Fruit f=Factory.getInstance("apple");  
  31.     f.eat();  
  32.     }  
  33. }  


但是工厂类如果这样写的话,就有一个问题,如果增加了水果,比如香蕉,那么在工厂类里面也要进行相关的修改了,这样不合理,而java的反射机制可以解决这个问题

[html]  view plain copy
  1.   
[java]  view plain copy
  1. package org1;  
  2.   
  3. interface Fruit {  
  4.     public void eat();  
  5. }  
  6.   
  7. class Apple implements Fruit {  
  8.     public void eat() {  
  9.         System.out.println("吃苹果。");  
  10.     }  
  11. }  
  12.   
  13. class Orange implements Fruit {  
  14.     public void eat() {  
  15.         System.out.println("吃橘子");  
  16.     }  
  17. }  
  18.   
  19. class Factory {  
  20.     public static Fruit getInstance(String className) {  
  21.         Fruit f = null;  
  22.         try {  
  23.             f = (Fruit) Class.forName(className).newInstance();  
  24.         } catch (Exception e) {  
  25.             e.printStackTrace();  
  26.         }  
  27.         return f;  
  28.     }  
  29. }  
  30.   
  31. public class CopyOfFactoryDemo03 {  
  32.     public static void main(String args[]) {  
  33.         Fruit f = Factory.getInstance("org1.Apple");  
  34.         f.eat();  
  35.     }  
  36. }  


利用java的反射机制,就能动态的实例化各种类了。 但是这个程序还是存在一个问题,就是主函数这里需要填入一个完整的类名称,不够方便,所以要增加配置文件来简化

[java]  view plain copy
  1. package org3;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileOutputStream;  
  6. import java.util.Properties;  
  7.   
  8. interface Fruit {  
  9.     public void eat();  
  10. }  
  11.   
  12. class Apple implements Fruit {  
  13.     public void eat() {  
  14.         System.out.println("吃苹果。");  
  15.     }  
  16. }  
  17.   
  18. class Orange implements Fruit {  
  19.     public void eat() {  
  20.         System.out.println("吃橘子");  
  21.     }  
  22. }  
  23.   
  24. class Factory {  
  25.     public static Fruit getInstance(String className) {  
  26.         Fruit f = null;  
  27.         try {  
  28.             f = (Fruit) Class.forName(className).newInstance();  
  29.         } catch (Exception e) {  
  30.             e.printStackTrace();  
  31.         }  
  32.         return f;  
  33.     }  
  34. }  
  35.   
  36. class PropertiesOperate{  
  37.     private Properties pro=null;  
  38.     private File file=new File("d:"+File.separator+"fruit.properties");  
  39.       
  40.     public PropertiesOperate(){  
  41.         this.pro=new Properties();  
  42.         if(file.exists()){  
  43.             try {  
  44.                 pro.loadFromXML(new FileInputStream(file));  
  45.             } catch (Exception e) {  
  46.                 e.printStackTrace();  
  47.             }  
  48.         }else{  
  49.             this.save();  
  50.         }  
  51.     }  
  52.     private void save(){  
  53.         this.pro.setProperty("apple","org3.Apple");  
  54.         this.pro.setProperty("orange""org3.Orange");  
  55.         try {  
  56.             this.pro.storeToXML(new FileOutputStream(this.file),"Fruit");  
  57.         } catch (Exception e) {  
  58.             e.printStackTrace();  
  59.         }  
  60.     }  
  61.     public Properties getProperties(){  
  62.         return this.pro;  
  63.     }  
  64. }  
  65.   
  66. public class CopyOfFactoryDemo04 {  
  67.     public static void main(String args[]) {  
  68.         Properties pro=new PropertiesOperate().getProperties();  
  69.         Fruit f= Factory.getInstance(pro.getProperty("apple"));  
  70.         f.eat();  
  71.     }  
  72. }  


加入配置文件问题就解决了,以后如果要增加新的水果类,都要在这个配置文件里面登记。这时我们可以说配置文件可以控制程序的执行,现在看起来有点像spring的ioc了。


其实最近在学spring 配置文件,一开始看一个好长的配置文件根本就不知道什么意思,是用来干什么的?而且看到好多的bean,百度了好多,说spring里面有ioc,还有aop(暂时还不理解aop是什么东西),可是要理解ioc就要先理解工厂模式,什么是接口,什么是java的反射。如果新手想要尽快的入门,可以尝试这个学习过程(当然我也是新手啦~~)。

下面我把我自己对spring的理解记下来:

其实我们如果理解了上面这个简单的三个程序就好办了,回顾上面的程序,该程序使用了工厂模式,把所有的类放在一个Factory里面,而为了动态的管理这些类(即使增加了新的Fruit类,这个工厂也不用变化),就用了java的反射机制。另外里面还设置了一个配置文件,使得某一长窜完整的类名称,比如org1.Apple可以用任意简短的名称来代替,比如apple。PS:如果这段话让读者感觉有点反胃,那就忘了这句废话,总之只要理解上面的程序,加上下面将要列举的小小的测试程序,我想就能理解spring配置文件的大致用途了。


简单的spring配置文件测试:

Person类

[java]  view plain copy
  1. package test2;  
  2.   
  3. public class Person {  
  4.     private String name;  
  5.     private int age;  
  6.     private Grade grade;  
  7.     public String getName() {  
  8.         return name;  
  9.     }  
  10.       
  11.     public Grade getGrade() {  
  12.         return grade;  
  13.     }  
  14.   
  15.     public void setGrade(Grade grade) {  
  16.         this.grade = grade;  
  17.     }  
  18.   
  19.     public void setName(String name) {  
  20.         this.name = name;  
  21.     }  
  22.   
  23.     public void setAge(int age) {  
  24.         this.age = age;  
  25.     }  
  26.   
  27.     public int getAge() {  
  28.         return age;  
  29.     }  
  30.   
  31.     public int getTotleGrade() {  
  32.         return grade.getEnglish()+grade.getMath();  
  33.     }  
  34. }  

Grade类

[java]  view plain copy
  1. package test2;  
  2.   
  3. public class Grade {  
  4.     private int math;  
  5.     private int english;  
  6.     public int getMath() {  
  7.         return math;  
  8.     }  
  9.     public void setMath(int math) {  
  10.         this.math = math;  
  11.     }  
  12.     public int getEnglish() {  
  13.         return english;  
  14.     }  
  15.     public void setEnglish(int english) {  
  16.         this.english = english;  
  17.     }  
  18. }  

Bean.xml配置文件(该文件只要放在test2包里面就好了)(堆积木工程开始咯~~)

[html]  view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"  
  4.   
  5. "http://www.springframework.org/dtd/spring-beans.dtd">  
  6. <beans>//很多豆豆  
  7.     <bean id="Person" class="test2.Person">//第一个豆豆,是一个Person类,id名字随便取,还要写上类的全名  
  8.         <property name="name">//下面开始把这个类里面的所有属性列出来,并赋值,至于你说难道一定要赋值吗?我想可以,我刚学,不知道  
  9.             <value>小龙</value>//这里的名字是通过程序里面的set来赋值的,不信你去掉程序里面相关的set,就出错了  
  10.         </property>  
  11.         <property name="age">  
  12.             <value>23</value>  
  13.         </property>  
  14.         <property name="grade">//这里有点特别,这个grade变量是一个对象,和一般的变量要区别对待  
  15.             <ref local="Grade"/>//这里指向了本配置文件里面一个名字叫Grade(即id=Grade)的bean  
  16.         </property>  
  17.     </bean>  
  18.     <bean id="Grade" class="test2.Grade">//同上  
  19.         <property name="math">  
  20.             <value>99</value>  
  21.         </property>  
  22.         <property name="english">  
  23.             <value>59</value>  
  24.         </property>  
  25.     </bean>  
  26. </beans>  

最后是Test测试类

[java]  view plain copy
  1. package test2;  
  2.   
  3. import org.springframework.beans.factory.BeanFactory;  
  4. import org.springframework.beans.factory.xml.XmlBeanFactory;  
  5. import org.springframework.core.io.ClassPathResource;  
  6. import org.springframework.core.io.Resource;  
  7.   
  8. import test.ExampleBean;  
  9.   
  10. public class Test {  
  11.     public static void main(String args[]){  
  12.         Resource input = new ClassPathResource("test2/Bean.xml");//Bean.xml的路径  
  13.   
  14.         System.out.println("resource is:" + input);  
  15.   
  16.         BeanFactory factory = new XmlBeanFactory(input);//把input扔到工厂里面去,这个工厂就能为你提供实例了(我也不知道能不能这样说)  
  17.   
  18.         Person person =(Person) factory.getBean("Person");//你要一个叫Person的东西,那好,工厂就去找“Person"给你  
  19.         Grade grade=(Grade)factory.getBean("Grade");  
  20.         System.out.println("姓名:"+person.getName());//person可以调用里面相关的方法,就相当于new了一个Person一样  
  21.         System.out.println("年龄:"+person.getAge());  
  22.         System.out.println("数学成绩:"+grade.getMath());  
  23.         System.out.println("英语成绩:"+grade.getEnglish());  
  24.         System.out.println("数学,英语总成绩:"+person.getTotleGrade());  
  25.     }  
  26. }  

如此看来,你在对比一开始的那个水果的程序,你会发现,spring配置文件,还是一个工厂,只不过换种形式一样,他管理所有的类,新建的类要到工厂里面去登记,不然就不能被主程序用,这就是为什么说ioc就是工厂模式的升级版。至于配置文件的书写,就跟堆积木一样,当然我现在学的还是表面东西。

相关文章