Spring中频繁使用了工厂模式,相对于一般的工厂模式做了优化,所以这里简单的模拟下,作为学习档案。
外部引用的jar包下载:http://www.jdom.org
Jdom参考文章:http://www.ibm.com/developerworks/cn/xml/x-jdom/
工厂模式一般有三种:
工厂模式在《Java与模式》中分为三类:
1)简单工厂模式(Simple Factory)
2)工厂方法模式(Factory Method)
3)抽象工厂模式(Abstract Factory)
介绍三类的好文章很多,google就好了。
区别:(这里工厂产生的类称为产品)
简单工厂模式:用来生产同一等级结构中的任意产品。对与增加新的产品,无能为力。
工厂方法 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
说白了,工厂方法虽然可以很好扩展产品种类,但是每次增加产品就要添加一个工厂,会导致工厂泛滥的情况,而抽象工厂模式每次可以生产一系列的产品,但是产品扩展方面局限性又大,spring中的工厂模式采用配置文件的方式很好的解决了他们的短板。
文件清单:BeanFactory.java:工厂接口类
BuildPathXMLApplicationContext.java:文件解析的实现
Movable.java:交通工具接口
Car.java:交工工具实现
Plane.java:交工工具实现
Test.java:测试类
applicationContext.xml:配置文件
文件清单一:BeanFactory.java
- package com.lzz.myspringIOC;
- /**
- * 定义工厂接口
- * @author Administrator
- *
- */
- public interface BeanFactory {
- public Object getBean(String beanName);
- }
文件清单二:BuildPathXMLApplicationContext.java
- package com.lzz.myspringIOC;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.jdom2.Document;
- import org.jdom2.Element;
- import org.jdom2.input.SAXBuilder;
- import org.jdom2.xpath.XPath;
- /**
- * 读取配置文件的bean,并生成实例对象,放在一个map中等待调用
- * @author Administrator
- *
- */
- public class BuildPathXMLApplicationContext implements BeanFactory {
- private Map<String, Object> container=new HashMap<String, Object>();
- public BuildPathXMLApplicationContext(String fileName) throws Exception{
- //通过xml的解析得到bean的id和class名称,并创建实例,存储到msp中
- SAXBuilder sb = new SAXBuilder();
- Document doc = sb.build(
- BuildPathXMLApplicationContext.class.getClassLoader().getResourceAsStream(fileName));
- Element root = doc.getRootElement();
- System.out.println(root);
- List list = XPath.selectNodes(root, "/beans/bean");
- System.out.println(list.size());
- for(int i=0;i<list.size();i++){
- Element beans = (Element) list.get(i);
- String id = beans.getAttributeValue("id");
- String clazzName=beans.getAttributeValue("class");
- System.out.println(id+" "+clazzName);
- container.put(id, Class.forName(clazzName).newInstance());
- }
- }
- public Object getBean(String beanName){
- return container.get(beanName);
- }
- }
文件清单三:Movable.java
- package com.lzz.myspringIOC;
- /**
- * 所有交通工具要实现的类
- * @author lzz
- *
- */
- public interface Movable {
- public void run();
- }
文件清单四:Car.java
- package com.lzz.myspringIOC;
- public class Car implements Movable{
- public void run(){
- System.out.println("小汽车。。。嘀嘀嘀");
- }
- }
文件清单五:Plane.java
- package com.lzz.myspringIOC;
- public class Plane implements Movable {
- public void run() {
- System.out.println("plane.......");
- }
- }
文件清单六:Test.java
- package com.lzz.myspringIOC;
- /**
- * 添加新的"产品"的时候,只要修改配置文件就可以使用了
- * 解决了工厂方法的不能生产系列"产品"的问题
- * 又解决了抽象工厂方法中不能添加"新产品"的问题
- * @author lzz
- *
- */
- public class Test {
- public static void main(String[] args) throws Exception {
- BeanFactory bf=new BuildPathXMLApplicationContext("com/lzz/myspringIOC/applicationContext.xml");
- //配置文件的CLASSPATH下的路径
- Object o=bf.getBean("v"); //配置文件中bean的id属性,是car还是plane只要修改配置文件就好了
- Movable m=(Movable)o; //这里使用接口实现多态,当配置文件更改的时候,就不需要更改了
- m.run();
- }
- }
文件清单七:applicationContext.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <beans>
- <bean id="v" class="com.lzz.myspringIOC.Plane">
- </bean>
- </beans>
测试结果:
- [Element: <beans/>]
- 1
- v com.lzz.myspringIOC.Plane
- plane.......