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

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 }
问题:若增加新水果,如香蕉,则工厂类也要修改.
解决: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 }
问题:创建实例时,需要提供“完整的类名”

1 public class FactoryDemo2 { 2 public static void main(String args[]) { 3 Fruit f = Factory.getInstance("org.Orange"); 4 f.eat(); 5 } 6 }
解决:增加“配置文件”优化.
三、增加“配置文件”:

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 }

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 }
通过配置文件,可以控制程序的执行,现在看起来有点像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 }

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 }
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>
测试类

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