容器工厂(原型)

容器工厂

对于容器工厂的了解可以是:创建一个核心容器,用于存放已经注册的实例。

学习过spring 的童鞋都知道,Spring 框架里面便有一个巨大的容器。

而本次学习的容器工厂便是参照Spring的理念。

通过解析XML读取里面的属性,并利用反射来创建改实现类的实例。

以下是我们需要准备的类

我们先试用手机的案例进行学习。

 

package factory;

/**
 * 手机
 */
public abstract class Phone {

    /**
     * 抽象的打电话的行为
     */
   public abstract void call();

}
/**
 * OppO
 */
public class OppoPhone extends Phone {
    @Override
    public void call() {
        System.out.println("使用Oppo手机打电话");
    }
}
package factory;

/**
 * 小米
 */
public class MiPhone extends Phone {
    @Override
    public void call() {
        System.out.println("使用小米手机打电话");
    }
}

 

创建好工厂后,我们在来配置XML文件,

beans.xml文件创建在src目录下

<?xml version="1.0" encoding="UTF-8"?>

<beans>
    <!-- bean可以是任意的对象,id是为这个对象在容器中的唯一标识
         class属性指定对象的完整类名
         scope表示对象的创建形式,单例还是原型,默认是单例-->
    <bean id="OppoPhone" class="factory.OppoPhone" scope="singleton"/>
    <bean id="MiPhone" class="factory.MiPhone"/>
</beans>

 

创建好beans.xml后重点来了,

我们要创建一个容器

 通过解析XML读取里面的属性,并利用反射来创建改实现类的实例

解析XML配置文件,我们需要用到dom4j。

 

下面是开始创建容器

package containerfactory;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 容器工厂
 * Created by Administrator on 2017/11/27.
 */
public class ContainerFactory{
    //创建一个核心容器,用于存放所有已经注册的实例
    private static Map<String,Object> container = new HashMap<String,Object>();

//初始化配置文件,使用dom4j来解析
    public ContainerFactory(String resourcePath){
        init(resourcePath);
    }
/**
     * 初始化容器
     * @param resourcePath 传入xml文件名
     */
    private void init(String resourcePath){
        //创建SAX解析器
        SAXReader reader = new SAXReader();

        try {
            //读取xml文件,并构建一个document对象
            Document doc =  reader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath));
            //获取document的根元素
            Element root = doc.getRootElement();
            //获取所有的元素
            List<Element> list = root.elements();
            //循环遍历,解析子元素的属性
            for(Element e:list){
                //获取id属性的值
                String id = e.attributeValue("id");
                //获取clas属性的值
                String className=e.attributeValue("class");
                //将信息放入容器中
                container.put(id,Class.forName(className).newInstance());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 提供一个从容器中获取实例的方法
     */
    public Object getBean(String id){
        return container.get(id);
    }

    /**
     * 重载一个泛型的方法
     */
    public <T> T getBean(String id,Class<T> clazz){
        return (T) container.get(id);
    }
}   
}

主方法入口

测试一

public class Main {
    public static void main(String[] args) {
        ContainerFactory factory = new ContainerFactory("beans.xml");

        Phone phone1 = (Phone) factory.getBean("MiPhone");
        Phone phone2 = (Phone) factory.getBean("MiPhone");
        phone1.call();
        System.out.println(phone1==phone2);
    }
}

结果为:

使用Oppo手机打电话

true


测试二

public class Main {
    public static void main(String[] args) {
        ContainerFactory factory = new ContainerFactory("beans.xml");

        Phone phone1 =  factory.getBean("OppoPhone", Phone.class);
        Phone phone2 = factory.getBean("MiPhone",Phone.class);
        System.out.println(phone1==phone2);
    }
}

结果为:false

posted @ 2017-11-27 20:51  信息界的搬运工  阅读(479)  评论(0编辑  收藏  举报