循序渐进学习设计模式——创建型模式——工厂设计模式
关于工厂设计模式:顾名思义,工厂代表着加工制作,生活中的日常用品、汽车零件等等一系列的东西,都是由工厂加工而成,那么代码是否也能这样呢?
在面向对象思想中,最关键的词就是“对象”,我们在使用面向对象思想编程时,第一件事就是“创建对象(new)”。
但是,当我们面对大量的类,甚至是一些相似的类,在使用时都需要不断的new,比如当我们要使用一个“狗”的对象,那就要创建“狗”这个对象,要使用“猫”这个对象,就必须要创建“猫”这个对象
这样当我们每次需要使用一个新的类,就要去new一个新的对象出来,当我们的需求很多时,new的操作就会让我们感觉到疲惫。那么,有没有一个方法,可以让我们省去new这个步骤呢?
方法就是使用工厂设计模式,我们定义一个工厂类,把new的过程存进工厂的方法中,当我们需要哪个对象,就直接调用工厂中的方法。
举个例子,当我们需要使用“狗和猫”两个对象,将new的过程存入工厂中。
虽然在我们的主类中的确不需要进行new这个过程,但是代码量并没有减少,因为获取“狗”对象和获得“猫”对象需要分别调用两个方法。
那么,如果可以用同一个方法就可以得到不同对象就可以让工厂更加遍历。
通过参数返回不同类型子类对象,使用不同的参数来获取不同的对象。
经过改进后的可以只通过一个方法就可以返回各种需要的(只能是同一个父类)对象,也就是说在上面的代码中,只能返回继承了Animal的对象。
那么此时的改进工厂的思路就是可以返回任意类型的对象,如何实现?
此时工厂的设计只需要满足两个条件:
1. 能够创建任意类型的对象
2. 能返回任意类型的对象。
那么此时延伸出的问题就是:
如何能够创建任意类型的对象?使用反射
如何返回任意类型的对象? 返回值设置成Object类型
此时的工厂已经初具规模,但是仍然存在问题。
如果是接口怎么处理?接口无法创建对象。
当类型是Object时,每次调用方法都需要强制类型转换,太麻烦。
此时的问题如何解决?使用泛型来解决返回值问题
此时,工厂只剩下一个问题,接口怎么处理?
接口无法创建对象,所以此时接口的实现类对象就是解决办法,返回此接口的实现类对象即可。
那么如何获得接口的实现类对象?使用配置文件
由于XML约束的存在,是的每一个bean标签中都具有id和className两个属性,所以,将接口名设置为id值,将实现类名设置为className值。
在工厂中的方法同样传入类对象参数,使用反射(getSimpleName方法)来获取接口名。
之后使用dom4j和xpath对XML进行解析,通过接口名来获取配置文件中的className的值,也就是实现类对象的名字。
有了实现类对象,就可以通过反射(Class.forName.newInstance)来创建实例对象
最后将此对象使用泛型返回,就得到了一个接口的实现类对象。
至此,工厂的设计得到的全面的完善(工厂中读取配置文件地址仍可以使用类加载器改进),可以返回任意类型的实例对象,并且可以返回接口的实现类对象。
使用工厂后,在需要创建接口的实现对象时,如果要使用同一个接口的不同实现类,只需要修改同一个接口的className的值即可。如果要使用不同的接口,只需要新增一个标签即可。
测试用例结果:
工厂设计模式最终版(使用类加载器读取配置文件地址)
public class BeanFactory { public static <T>T getBean(Class<T> clz) throws Exception { //clz 表示接口的类对象,获取接口名 String simpleName = clz.getSimpleName(); //此时就是解析XML文件的过程,通过接口名来查找实现类名 SAXReader saxReader = new SAXReader(); /* 使用类加载器读取配置文件 配置文件必须在src目录下才能使用类加载器 */ Document document = saxReader.read(BeanFactory.class.getClassLoader().getResource("beans2.xml")); Element element = (Element)document.selectSingleNode("//bean[@id='" + simpleName + "']"); //配置文件中完整的实现类名称 String className = element.attributeValue("className"); //此刻通过实现类名称创建实例对象并返回(反射) Object o = Class.forName(className).newInstance(); return (T)o; } }
前人栽树,后人乘凉。
经典的事物永远都不会褪色。
设计模式正是前人们经过认真的探索和思考,代表了最佳的实践,由于设计模式的存在使得我们可以直接地去体验这些经典。