工厂模式是最经常使用的一种建立型模式,一般所说的工厂模式通常是指工厂方法模式。本篇是是工厂方法模式的“小弟”,咱们能够将其理解为工厂方法模式的预备知识,它不属于GoF 23种设计模式,但在软件开发中却也应用地比较频繁。此外,工厂方法模式还有一位“大哥”—抽象工厂模式,会在后面进行介绍。程序员
简单工厂模式(Simple Factory) | 学习难度:★★☆☆☆ | 使用频率:★★★☆☆ |
M公司想要基于C#语言开发一套图表库,该图表库能够为应用系统提供各类不一样外观的图标,例如柱状图、饼状图或折线图等。M公司图表库设计开发人员但愿为应用系统开发人员提供一套灵活易用的图表库,并且能够较为方便地对图表库进行扩展,以便于在未来增长一些新类型的图表。设计模式
M公司的程序员提出了一个初始设计方案,将全部图表的实现代码封装在一个Chart类中,其框架代码以下所示:app
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)方法,所以简单工厂模式又被称为静态工厂方法模式,它属于建立型模式。this
简单工厂模式的要点在于:当你须要什么,只须要传入一个正确的参数,就能够获取你所需的对象,而无须知道其建立细节。spa
简单工厂模式包含3个角色:设计
在简单工厂模式中,客户端经过工厂类来建立一个产品类的实例,而无须直接使用new关键字来建立对象。(能够看出,它是工厂模式家族中最简单的一员)code
为了将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(); } }
运行结果以下:
刘伟,《设计模式的艺术—软件开发人员内功修炼之道》