工厂模式是最常用的一种创建型模式,通常所说的工厂模式一般是指工厂方法模式。本篇是是工厂方法模式的“小弟”,我们可以将其理解为工厂方法模式的预备知识,它不属于GoF 23种设计模式,但在软件开发中却也应用地比较频繁。此外,工厂方法模式还有一位“大哥”—抽象工厂模式,会在后面进行介绍。
简单工厂模式(Simple Factory) | 学习难度:★★☆☆☆ | 使用频率:★★★☆☆ |
---|
M公司想要基于C#语言开发一套图表库,该图表库可以为应用系统提供各种不同外观的图标,例如柱状图、饼状图或折线图等。M公司图表库设计开发人员希望为应用系统开发人员提供一套灵活易用的图表库,而且可以较为方便地对图表库进行扩展,以便于在将来增加一些新类型的图表。
M公司的程序员提出了一个初始设计方案,将所有图表的实现代码封装在一个Chart类中,其框架代码如下所示:
public class Chart
{
private string type; // 图表类型
public Chart(object[][] data, string type)
{
this.type = type;
if (this.type.Equals("histogram", StringComparison.OrdinalIgnoreCase))
{
// 初始化柱状图
}
else if (this.type.Equals("pie", StringComparison.OrdinalIgnoreCase))
{
// 初始化饼状图
}
else if (this.type.Equals("line", StringComparison.OrdinalIgnoreCase))
{
// 初始化折线图
}
}
public void Display()
{
if (this.type.Equals("histogram", StringComparison.OrdinalIgnoreCase))
{
// 显示柱状图
}
else if (this.type.Equals("pie", StringComparison.OrdinalIgnoreCase))
{
// 显示饼状图
}
else if (this.type.Equals("line", StringComparison.OrdinalIgnoreCase))
{
// 显示折线图
}
}
}
客户端代码通过调用Chart类的构造函数来创建图表对象,根据参数type的不同可以得到不同类型的图标,然后再调用Display()方法来显示相应的图表。
但是,不难看出,Chart类是一个巨大的类,存在很多问题:
简单工厂模式并不属于GoF 23种经典设计模式,但通常将它作为学习其他工厂模式的基础。
简单工厂(Simple Factory)模式:定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法模式,它属于创建型模式。
简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需的对象,而无须知道其创建细节。
简单工厂模式包含3个角色:
在简单工厂模式中,客户端通过工厂类来创建一个产品类的实例,而无须直接使用new关键字来创建对象。(可以看出,它是工厂模式家族中最简单的一员)
为了将Chart类的职责分离,同时将Chart对象的创建和使用分离,M公司开发人员决定使用简单工厂模式对图表库进行重构,重构后的结构图如下所示:
(1)抽象产品角色:IChartable接口
public interface IChartable
{
void Display();
}
(2)具体产品角色:各种图表类型
public class HistogramChart : IChartable
{
public HistogramChart()
{
Console.WriteLine("创建柱状图...");
}
public void Display()
{
Console.WriteLine("显示柱状图...");
}
}
public class LineChart : IChartable
{
public LineChart()
{
Console.WriteLine("创建折线图...");
}
public void Display()
{
Console.WriteLine("显示折线图...");
}
}
public class PieChart : IChartable
{
public PieChart()
{
Console.WriteLine("创建饼状图...");
}
public void Display()
{
Console.WriteLine("显示饼状图...");
}
}
(3)工厂角色:ChartFactory
public class ChartFactory
{
public static IChartable GetChart(string type)
{
IChartable chart = null;
if (type.Equals("histogram", StringComparison.OrdinalIgnoreCase))
{
chart = new HistogramChart();
Console.WriteLine("初始化设置柱状图...");
}
else if (type.Equals("pie", StringComparison.OrdinalIgnoreCase))
{
chart = new PieChart();
Console.WriteLine("初始化设置饼状图...");
}
else if (type.Equals("line", StringComparison.OrdinalIgnoreCase))
{
chart = new PieChart();
Console.WriteLine("初始化设置折线图...");
}
return chart;
}
}
(4)客户端调用:
public static void Main()
{
IChartable chart = ChartFactory.GetChart("histogram");
if (chart != null)
{
chart.Display();
}
chart = ChartFactory.GetChart("pie");
if (chart != null)
{
chart.Display();
}
}
运行结果如下:
在客户端代码中,使用工厂类的静态方法来创建具体产品对象,如果需要更换产品,只需要修改静态工厂方法中的参数即可。例如:将柱状图改为饼状图,只需要将代码:
IChartable chart = ChartFactory.GetChart("histogram");
改为:
IChartable chart = ChartFactory.GetChart("pie");
M公司开发人员发现在创建具体Chart对象时,每次更换一个Chart对象都需要修改客户端中静态工厂方法的参数,客户端代码需要重新编译,这对于客户端而言,是违反了开闭原则的。于是,开发人员希望有一种方法能够在不修改客户端代码地前提下更换具体产品对象。
因此,他们考虑使用配置文件(XML)来实现:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="charttype" value="histogram"/>
</appSettings>
</configuration>
客户端因此改为:
public static void Main()
{
string type = AppConfigHelper.GetChartType(); // 读取配置文件中的charttype
if (string.IsNullOrEmpty(type))
{
return;
}
IChartable chart = ChartFactory.GetChart(type);
if (chart != null)
{
chart.Display();
}
}
运行结果如下:
刘伟,《设计模式的艺术—软件开发人员内功修炼之道》
作者:周旭龙
出处:http://edisonchou.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。