首页 > 技术文章 > SpringIoc 和 工厂模式(反射实现)

listened 2017-12-16 12:09 原文

一、先演示 “简单工厂”:

 1 package org;
 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         if (className.equals("apple")) {
23             f = new Apple();
24         }
25         if (className.endsWith("orange")) {
26             f = new Orange();
27         }
28         return f;
29     }
30 }
31 
32 public class FactoryDemo {
33     public static void main(String args[]) {
34         Fruit f = Factory.getInstance("apple");
35         f.eat();
36     }
37 }
View Code

问题:若增加新水果,如香蕉,则工厂类也要修改.

解决:java的反射机制.

二、修改“工厂类”:

 1 //工厂类(修改)
 2 class Factory { 
 3     public static Fruit getInstance(String className) {
 4         Fruit f = null;
 5         try {  
 6             f = (Fruit) Class.forName(className).newInstance();  
 7         } catch (Exception e) {  
 8             e.printStackTrace();  
 9         }  
10         return f;
11     }
12 }
View Code

问题:创建实例时,需要提供“完整的类名”

1 public class FactoryDemo2 {
2     public static void main(String args[]) {
3         Fruit f = Factory.getInstance("org.Orange");
4         f.eat();
5     }
6 }
View Code

解决:增加“配置文件”优化.

三、增加“配置文件”:

 1 class PropertiesOperate{  
 2     private Properties pro=null;  
 3     private File file=new File("d:"+File.separator+"fruit.properties");  
 4       
 5     public PropertiesOperate(){  
 6         pro=new Properties();  
 7         if(file.exists()){  
 8             try {  
 9                 pro.loadFromXML(new FileInputStream(file));  
10             } catch (Exception e) {  
11                 e.printStackTrace();  
12             }  
13         }else{  
14             this.save();  
15         }  
16     }  
17     private void save(){  
18         pro.setProperty("apple","org.Apple");  
19         pro.setProperty("orange", "org.Orange");  
20         try {  
21             pro.storeToXML(new FileOutputStream(this.file),"Fruit");  
22         } catch (Exception e) {  
23             e.printStackTrace();  
24         }  
25     }  
26     public Properties getProperties(){  
27         return pro;  
28     }  
29 } 
View Code
1 public class FactoryDemo3 {
2     public static void main(String args[]) {
3         Properties pro=new PropertiesOperate().getProperties();  
4         Fruit f= Factory.getInstance(pro.getProperty("orange")); 
5         f.eat();
6     }
7 }
View Code

通过配置文件,可以控制程序的执行,现在看起来有点像spring的ioc了。

 

该程序使用了工厂模式,把所有的类放在一个Factory里面,而为了动态的管理这些类(即使增加了新的Fruit类,这个工厂也不用变化),就用了java的反射机制。

另外,通过配置文件,使得一长串完整的类名称(如org.Apple)可用任意简短的名称来代替(如apple)。

 

四、简单的spring配置文件测试

 

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

bean .xml 类

 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="test.Person"><!-- 第一个bean,是一个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="test.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>  
View Code

测试类

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

 

对比前面的那个“Fruit程序”,你会发现,spring配置文件,还是一个工厂(只是换种形式一样),它管理所有的类,新建的类要到工厂里面去登记,不然就不能被主程序用,这就是为什么说ioc就是工厂模式的升级版。

推荐阅读