简单工厂设计模式

简单工厂设计模式

概念

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

角色

  • 工厂角色
    简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
  • 抽象产品角色
    简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  • 具体产品角色
    是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

UML图如下
在这里插入图片描述

简单工厂模式的优缺点

优点
  • 工厂类包含必要的判断逻辑,可以决定在什么时候创建那个产品的实例,客户端可以免除直接创建对象的职责,而仅仅消费产品,实现了对象创建和使用的分离
  • 客户端无需知道所创建的产品的具体类名,只需要知道产品类对应的不同参数即可
  • 可以引入配置文件,在不修改客户端代码的情况下更换和新增具体的产品类
缺点
  • 工厂类职责过重,一旦不能正常工作,整个系统都要受到影响
  • 会增加系统中类的个数,增加了系统的复杂度和理解难度
  • 系统扩展困难,一旦添加新产品类,就不得不修改逻辑工厂
  • 使用静态工厂方法,不能形成基于继承的等级结构

适合环境

  • 工厂类负责创建的对象较少,不会使得工厂的逻辑过于复杂
  • 客户端只需要知道传入工厂的参数,而不需要关心对象如何创建

例子

某公司需要基于java开发一套图表工具,可以提供不同的图表如:柱状图(HistogramChart),饼状图(PieChart),折线图(LineChart)。该公司需要我们为其提供一套灵活的图标库,通过传入不同的参数得到不同的图表来使用。

分析

我们先将实体与简单工厂的角色一一对应

  • 抽象产品角色: Chart
  • 具体产品角色: HistogramChart,PieChart,LineChart
  • 工厂角色: ChartFactory

看不懂不要紧,我们先看UML图,在看代码应该就能理解了
在这里插入图片描述

编码

Chart.java

package cn.kevinlu98.simplefactory;

/**
 * @Author: Kevin·Lu
 * @Date: 8:26 PM 2019/7/25
 * @Description:抽象图表接口,充当抽象的产品类
 */
public interface Chart {
    public static final String CHART_HISTOGRAM = "histogram";

    public static final String CHART_PIE = "pie";

    public static final String CHART_LINE = "line";

    public void display();
}

HistogramChart.java

package cn.kevinlu98.simplefactory;

/**
 * @Author: Kevin·Lu
 * @Date: 8:29 PM 2019/7/25
 * @Description: 柱状图,充当具体的产品
 */
public class HistogramChart implements Chart {
    public HistogramChart() {
        System.out.println("创建柱状图");
    }

    @Override
    public void display() {
        System.out.println("显示柱状图");
    }
}

LineChart.java

package cn.kevinlu98.simplefactory;

/**
 * @Author: Kevin·Lu
 * @Date: 8:32 PM 2019/7/25
 * @Description: 折线图类,充当具体的产品类
 */
public class LineChart implements Chart {
    public LineChart() {
        System.out.println("创建折线图");
    }

    @Override
    public void display() {
        System.out.println("显示折线图");
    }
}

PieChart.java

package cn.kevinlu98.simplefactory;

/**
 * @Author: Kevin·Lu
 * @Date: 8:31 PM 2019/7/25
 * @Description: 饼状图类,充当具体的产品类
 */
public class PieChart implements Chart {
    public PieChart() {
        System.out.println("创建了饼状图");
    }

    @Override
    public void display() {
        System.out.println("显示饼状图");
    }
}

ChartFactory.java

package cn.kevinlu98.simplefactory;

/**
 * @Author: Kevin·Lu
 * @Date: 8:34 PM 2019/7/25
 * @Description: 图表工厂,充当工厂类
 */
public class ChartFactory {
    /**
     * 静态工厂方法
     *
     * @param type
     * @return
     */
    public static Chart getChart(String type) {
        Chart chart = null;
        if (type.equalsIgnoreCase(Chart.CHART_HISTOGRAM)) {
            chart = new HistogramChart();
            System.out.println("初始化设置柱状图");
        } else if (type.equalsIgnoreCase(Chart.CHART_PIE)) {
            chart = new PieChart();
            System.out.println("初始化设置饼状图");
        } else if (type.equalsIgnoreCase(Chart.CHART_LINE)) {
            chart = new LineChart();
            System.out.println("初始化设置折线图");
        }
        return chart;
    }
}

Client.java

package cn.kevinlu98.simplefactory;

/**
 * @Author: Kevin·Lu
 * @Date: 8:38 PM 2019/7/25
 * @Description: 简单工厂模式 客户端测试
 */
public class Client {
    public static void main(String[] args) {
        String type = "histogram";
        Chart chart = ChartFactory.getChart(type);
        chart.display();
    }
}

运行结果

在这里插入图片描述

我们需要不同的图表时只需要更改客户端的type变量的值就可以了

优化

不难发现我们像上面那样设计的程序必须通过修改客户端中的main方法的type变量的值来进行创建不同的图表,代码一旦更改就需要重新编译,违反了开闭原则

我们可以通过一种常用的方法解决,让客户端不更改代码的前提下更换具体的对象
在java语言中常用的配置就是XML了

创建config.xml

<?xml version="1.0" encoding="utf-8" ?>
<config>
    <chartType>line</chartType>
</config>

编写XML工具类,XMLUtil.java

package cn.kevinlu98.simplefactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;

/**
 * @Author: Kevin·Lu
 * @Date: 8:41 PM 2019/7/25
 * @Description: 读取xml文件中的字符串参数
 */
public class XMLUtil {
    public static String getChartType() {
        try {
            //创建文档对象
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new File("src/cn/kevinlu98/simplefactory/config.xml"));

            //获取包含图表类型的文本节点
            NodeList nl = document.getElementsByTagName("chartType");
            Node classNode = nl.item(0).getFirstChild();
            String chartType = classNode.getNodeValue();
            return chartType;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

修改客户端代码,Client.java

package cn.kevinlu98.simplefactory;

/**
 * @Author: Kevin·Lu
 * @Date: 8:38 PM 2019/7/25
 * @Description: 简单工厂模式 客户端测试
 */
public class Client {
    public static void main(String[] args) {
        String type = XMLUtil.getChartType();
        Chart chart = ChartFactory.getChart(type);
        chart.display();
    }
}

重新运行

在这里插入图片描述

现在我们需要更换对象时只需要在XML中配置就好了

至此,简单工厂设计模式介绍完成,希望能帮助到您

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值