您的位置:首页 > 其它

简单工厂模式的一种扩展

2015-01-10 22:53 459 查看
关于简单工厂模式的简单介绍请看这里:

/article/1610296.html

同时,这篇博客其实也是对上文的再次扩展。

我们知道简单工厂模式的一个巨大的不足就是

系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

例如经典的工厂代码一般如下:

public class ChartFactory {  
    //静态工厂方法  
    public static Chart getChart(String type) {  
        Chart chart = null;  
        if (type.equalsIgnoreCase("histogram")) {  
            chart = new HistogramChart();  
            System.out.println("初始化设置柱状图!");  
        }  
        else if (type.equalsIgnoreCase("pie")) {  
            chart = new PieChart();  
            System.out.println("初始化设置饼状图!");  
        }  
        else if (type.equalsIgnoreCase("line")) {  
            chart = new LineChart();  
            System.out.println("初始化设置折线图!");              
        }  
        return chart;  
    }  
}
一旦我增加一个新的chart,就得修改getChart这个类里面的逻辑。而且一堆if else看着实在难受。所以,我可以让每个chart自己判断。

看代码

package simplefactory;

public  interface Chart {  //总的chart接口
    public boolean match(String chart);
    public void display();
    public void init();
}


package simplefactory;

public class  HistogramChart implements Chart { //柱状图的类,饼状图与折线图类似 不再赘述
    public HistogramChart() {
        System.out.println("创建柱状图!");
    }
    
    public void display() {
        System.out.println("显示柱状图!");
    }
    
    public boolean match(String chart) {
        if (chart.equals("hisrogram"))
            return true;        
        return false;
    }

    @Override
    public void init() {
        System.out.println("初始化设置柱状图!");
    }
}


在这里也有一个xml,如下

其中chartType是所有的chart类型

need 是我们所需要的chart类型

<?xml version="1.0" encoding="UTF-8"?>
<config>  
    <chartType>simplefactory.HistogramChart</chartType>  
    <chartType>simplefactory.LineChart</chartType>
    <chartType>simplefactory.PieChart</chartType>
    
    
    <need>line</need>
</config>


分析xml的工具类如下:

package xml;

import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;

public class XMLUtil {
    // 该方法用于从XML配置文件中提取图表类型,并返回类型名
    // 这个类和上文提到的博客里面的差别在于 方法的参数
    public static String[] getChartType(String choice) {
        try {
            // 创建文档对象
            DocumentBuilderFactory dFactory = DocumentBuilderFactory
                    .newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File("src/xml/xmlutil.xml"));

            // 获取包含图表类型的文本节点
            NodeList nl = doc.getElementsByTagName(choice);

            String[] names = new String[nl.getLength()];
            for (int i = 0; i < nl.getLength(); i++) {
                names[i] = nl.item(i).getFirstChild().getNodeValue().trim();
            }
            return names;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}


最后,我们看看重构后的工厂

package simplefactory;

import java.util.ArrayList;

import org.apache.catalina.tribes.membership.StaticMember;

import xml.XMLUtil;

public class ChartFactory {
    
    //产品候选列表
    static ArrayList<Chart> charts=new ArrayList<Chart>();
    //需要的产品
    static String[] choise=new String[1];
    
    public static Chart getChart(){
        charts=ChartFactory.getAllChart();
        choise=XMLUtil.getChartType("need");
        for (int i = 0; i < charts.size(); i++)
            if (charts.get(i).match(choise[0]))
                return charts.get(i);

        return null;        
    }
    
    public static ArrayList<Chart> getAllChart() {
        //获得所有chart的路径
        String[] name = XMLUtil.getChartType("chartType");
        ArrayList<Chart> chart = new ArrayList<Chart>();

        try {
            //将chart全部new出来
            for (int i = 0; i < name.length; i++)
                chart.add((Chart) Class.forName(name[i]).newInstance());
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return chart;
    }
}


测试如下

package simplefactory;

public class ChartTest {

    public static void main(String[] args) {

        Chart chart=ChartFactory.getChart();
        System.out.println("------");
        chart.init();
        chart.display();
    }
}
结果如下:

创建柱状图!

创建折线图!

创建饼状图!

------

初始化设置折线图!

显示折线图!

如果想要饼状图,只需要把xml改成

<need>pie</need>

总结一下:

我现在已经不能说这次重构的结果仍然是工厂模式了。工厂模式是生产一个匹配于所给参数的产品。而我这个等于是把工厂支持的产品先都生产出来,再一个一个问:人家需要的是这个产品,你看你行不?

好处就在于,以后即使要扩展新的产品,只用改xml就好。不用对工厂做改变。

而且我们告别了一大堆if else。

感谢glt
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: