从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式就是由一个工厂类根据传入的参量决定创建出哪一种产品类的实例。简单工厂模式是工厂 模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现,学习了此模式可以为后面的很多中模式打下基础。
简单工厂模式参与者:
工厂类:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体的类实现。
抽象产品角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或她们共同拥有的接口。一般由接口或抽象类实现。
具体产品角色:工厂方法模式所创建的任何对象都是这个角色的实例,由具体类实现。
下面我们通过一个海产品工厂来实现简单工厂模式:
一、抽象产品角色:
//抽象产品角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或她们共同拥有的接口。一般由接口或抽象类实现。
//在本例中就是ISeaFood接口
public interface ISeaFood
{
//定义在此接口中需要实现的方法
void TradeIn(); //买入
void Keep();//喂养
void TradeOut(); //卖出
}
#endregion
二、具体产品角色:
//这些产品都要实现ISeaFood接口
//具体产品角色:工厂方法模式所创建的任何对象都是这个角色的实例,由具体类实现。本例就是下面定义的三种海产品类
#region 定义BarramundiFish产品
public class BarramundiFish : ISeaFood
{
#region BarramundiFish构造函数
public BarramundiFish()
{
}
#endregion
#region 实现BarramundiFish的ISeaFish接口成员
public void TradeIn()
{
Console.WriteLine("买入BarramundiFish");
}
public void Keep()
{
Console.WriteLine("喂养BarramundiFish");
}
public void TradeOut()
{
Console.WriteLine("卖出BarramundiFish");
}
#endregion
}
#endregion
#region 定义SnowCrab产品
public class SnowCrab : ISeaFood
{
#region SnowCrab构造函数
public SnowCrab()
{
}
#endregion
#region 实现SnowCrab的ISeaFish接口成员
public void TradeIn()
{
Console.WriteLine("买入SnowCrab");
}
public void Keep()
{
Console.WriteLine("喂养SnowCrab");
}
public void TradeOut()
{
Console.WriteLine("卖出SnowCrab");
}
#endregion
}
#endregion
#region 定义JellyFish产品
public class JellyFish : ISeaFood
{
#region JellyFish构造函数
public JellyFish()
{
}
#endregion
#region 实现JellyFish的ISeaFish接口成员
public void TradeIn()
{
Console.WriteLine("买入JellyFish");
}
public void Keep()
{
Console.WriteLine("喂养JellyFish");
}
public void TradeOut()
{
Console.WriteLine("卖出JellyFish");
}
#endregion
}
#endregion
#endregion
三、工厂类:
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SeafoodSimpleFactory
{
#region 工厂类:实现SeaFood简单工厂
//工厂类:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体的类实现。
public class SeafoodFarm
{
#region 工厂一
//工厂一:使用switch方法来判断需要出产哪一种SeaFood产品,此产品名由seaFoodName参数指明
public static ISeaFood SeafoodFactory(string seaFoodName)
{
switch (seaFoodName)
{
case "BarramundiFish": return new BarramundiFish();
case "SnowCrab": return new SnowCrab();
case "JellyFish": return new JellyFish();
default: return null;
}
}
#endregion
#region 工厂二
//工厂二:使用Type与Activator配合通过反射来实现出产对应的产品,此产品类型由seafoodType来指明
//System.Type类,它对于反射起着核心的作用。我们可以使用 Type 对象的方法、字段、属性和嵌套类来查找有关该类型的所有信息。
//System.Activator类,它包含特定的方法,用以在本地或从远程创建对象类型,或获取对现有远程对象的引用。
public static ISeaFood SeafoodFactory2(Type seaFoodType)
{
ISeaFood mySeaFood = null;
try
{
//Type mytype = Type.GetType(seaFoodName, true);
mySeaFood = (ISeaFood)Activator.CreateInstance(seaFoodType);
}
catch (TypeLoadException e)
{
Console.WriteLine("无法识别你想要创建的产品,异常捕获 - {0}", e.Message);
}
return mySeaFood;
}
#endregion
}
#endregion
}
四、客户调用:
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SeafoodSimpleFactory
{
class Program
{
static void Main(string[] args)
{
#region 工厂方式一
ISeaFood mySeaFood = SeafoodFarm.SeafoodFactory("BarramundiFish");
mySeaFood.TradeIn();
mySeaFood.Keep();
mySeaFood.TradeOut();
mySeaFood = SeafoodFarm.SeafoodFactory("SnowCrab");
mySeaFood.TradeIn();
mySeaFood.Keep();
mySeaFood.TradeOut();
mySeaFood = SeafoodFarm.SeafoodFactory("JellyFish");
mySeaFood.TradeIn();
mySeaFood.Keep();
mySeaFood.TradeOut();
#endregion
#region 工厂方式二
ISeaFood mySeaFood2 = SeafoodFarm.SeafoodFactory2(typeof(BarramundiFish));
mySeaFood2.TradeIn();
mySeaFood2.Keep();
mySeaFood2.TradeOut();
mySeaFood2 = SeafoodFarm.SeafoodFactory2(typeof(SnowCrab));
mySeaFood2.TradeIn();
mySeaFood2.Keep();
mySeaFood2.TradeOut();
mySeaFood2 = SeafoodFarm.SeafoodFactory2(typeof(JellyFish));
mySeaFood2.TradeIn();
mySeaFood2.Keep();
mySeaFood2.TradeOut();
Console.Read();
#endregion
}
}
}
此模式优缺点
1、工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅"消费"产品。简单工厂模式通过这种做法实现了对责任的分割。
2、当产品有复杂的多层等级结构时,工厂类只有自己,以不变应万变,就是模式的缺点。因为工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
3、系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,有可能造成工厂逻辑过于复杂,违背了"开放--封闭"原则(OCP).另外,简单工厂模式通常使用静态工厂方法,这使得无法由子类继承,造成工厂角色无法形成基于继承的等级结构。