设计模式之从简单工厂到泛型简单工厂
设计模式之简单工厂模式到泛型工厂
简单工厂模式(Simple Factory Pattern)又称为虽然23种设计模式中并不包含简单工厂模式,但是它是一种创建性模式应用的也相对比较广泛。在简单工厂模式中,可以根据参数的不同返回不同类的实例,被创建的实例通常都有相同的父类。
以下是该模式的模式结构图:
首先我们称创建的实例为产品
简单工厂模式的有以下几个特点:
Factory:工厂角色
Fruit:抽象产品类
Apple:具体产品类
Banana:具体产品类
在客户类中我们可以
Fruit fruit=Factory.getInstance("Apple");
当然我们也可以使用dom技术在xml中指定类名。
可见使用简单工厂模式有很多的优点:
1、将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易。
2、在调用工厂类的工厂方法时,由于工厂方法是静态方法,使用起来很方便,可通过类名直接调用,而且只需要传入一个简单的参数即可,在实际开发中,还可以在调用时将所传入的参数保存在XML等格式的配置文件中,修改参数时无须修改任何Java源代码。
但是这个模式也有一个很大的缺点:
下面我们来分析一下这个模式的代码和可维护性等等。
if(type.equals("Apple")){ new Apple(); }else if(type.equals("Banana")){ new Banana(); }
上面这个代码有一个很明显的问题:
1、假如我要在系统中添加一种水果类要怎么办?
2、若系统中的水果类有几十种的话,上面这段代码将变得异常臃肿,维护起来相当麻烦。
3、工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则是相违背的。
那么针对这个问题我想可不可以利用以前学过的泛型知识来解决这个问题
客户端代码:
GenericFactory factory = new GenericFactory<Fruit>(); Fruit fruit = factory.getInstance(Apple.class); fruit.eat();
这样我们再添加一个水果类,不需要修改GenericFactory的getInsance方法,很好的实现了开闭原则。甚至我们可以在客户端使用dom解析技术对XML文件进行解析:
下面是完整的代码:
public class GenericFactory<T extends Fruit> { public T getInstance(Class<T> genericCla) { T fruit = null; try { fruit = genericCla.newInstance(); } catch (Exception e) { e.printStackTrace(); } return fruit; } public static void main(String[] args) throws ClassNotFoundException { GenericFactory factory = new GenericFactory<Fruit>(); String className=DomUtil.getClassPath(); Class class1=Class.forName(className); Fruit fruit = factory.getInstance(class1); fruit.eat(); } }
我们只需要在config.xml指定要使用的具体水果类即可:
<?xml version="1.0" encoding="UTF-8"?> <beans> <bean> <className>com.zdx.design.patterns.genericFactory.Banana</className> </bean> </beans>
具体的DomUtil工具
package com.zdx.design.util; import java.io.File; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class DomUtil { public static String getClassPath() { String classPath=null; try { DocumentBuilderFactory builderFactory = DocumentBuilderFactory .newInstance(); DocumentBuilder documentBuilder = builderFactory .newDocumentBuilder(); Document document = documentBuilder.parse(new File("bin/config.xml")); Element root=document.getDocumentElement(); NodeList beans = root.getChildNodes(); for (int i = 0; i < beans.getLength(); i++) { Node nodeClass=beans.item(i); if(nodeClass.getNodeType()==Node.ELEMENT_NODE){ for(Node node=nodeClass.getFirstChild();node!=null;node=node.getNextSibling()){ if(node.getNodeType()==Node.ELEMENT_NODE){ if(node.getNodeName().equals("className")){ classPath= node.getFirstChild().getNodeValue(); } } } } } } catch (Exception e) { e.printStackTrace(); } return classPath; } }
以上两种模式都是简单工厂模式,只是实现的方式不一样第二种是用反射的方式代替了第一种方法创建产品对象的逻辑判断,第二种使系统更加灵活,扩充性更好,当新增一种水果类的时候并不需要对现有系统的代码进行修改很好的实现了开闭原则。
上一篇: 简单工厂模式
下一篇: 统一对象创建--简单工厂模式