工厂方法,又名工厂模式,属于创建型模式。
其目的是通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到子类。
所以,当你不知道你必须要创建的对象的类型时或者你希望在程序运行时决定你需要创建的类型时,可以考虑工厂方法。
结构需要角色如下:
IProduct(产品接口):工厂方法生产的产品接口;
Product(产品):产品接口的实现类;
IFactory(工厂接口):承载了工厂方法的接口;
ConcreteFactory(工厂):工厂接口的实现类;
实现在《设计模式 - 可复用的面向对象软件》一书中将工厂方法分为参数化工厂方法(简单工厂)和非参数化工厂方法(工厂模式)两种。
下面例子中,以鼠标为例。看看如何使用参数化工厂方法和非参数化工厂方法去实现一个鼠标的生产。
在以下示例中,开发语言均使用C#,在采用其它语言实现时,会有些许不同。
参数化工厂方法(简单工厂)
使用简单工厂去实现一个产品的生产,我们首先需要抽象出这个产品的接口,再分别由不同类型的产品去实现这个接口。之后,我们还需要一个承载工厂方法的工厂类来生产这个产品,供调用者使用。
public interface IMouse { string GetBrand(); } public class LogitechMouse : IMouse { public string GetBrand() { return "罗技-Logitech"; } } public class RazeMouse : IMouse { public string GetBrand() { return "雷蛇-Raze"; } } public class MouseFactory { public IMouse CreateMouse(string brand) { if (string.IsNullOrEmpty(brand)) { return null; } if(brand == "罗技") { return new LogitechMouse(); } else if (brand == "雷蛇") { return new RazeMouse(); } else { return null; } } } class Program { static void Main(string[] args) { //创建工厂 MouseFactory factory = new MouseFactory(); //通过工厂生产实体 IMouse mouseA = factory.CreateMouse("罗技"); IMouse mouseB = factory.CreateMouse("雷蛇"); Console.WriteLine($"MouseA的品牌是:{mouseA.GetBrand()}"); Console.WriteLine($"MouseB的品牌是:{mouseB.GetBrand()}"); Console.ReadKey(); } }示例中MouseFactory的CreateMouse函数就是所谓的工厂方法,调用者通过MouseFactory的实例调用工厂方法来获取具体的鼠标实体,工厂方法通过调用者的需求(入参)去生产相应类型的鼠标实体。
不难看出,示例中存在如下缺陷:
当调用者向工厂下达的需求不能够被工厂识别时,比如传入“罗技鼠标”(对于鼠标生产来讲,罗技与罗技鼠标没有本质区别),工厂将不能正确生产对应的鼠标实体。
当工厂增加新的鼠标种类时,就需要在MouseFactory的CreateMouse函数中增加if else语句,不符合开闭原则(对拓展开放,对修改关闭)。
为解决这两个问题,做出如下修改。
/// <summary> /// 鼠标常数,维护鼠标类的完全限定名 /// </summary> public class MouseBrandConst { public static readonly string Logitech = typeof(LogitechMouse).FullName; public static readonly string Raze = typeof(RazeMouse).FullName; } public class MouseFactory { public IMouse CreateMouse(string brand) { if (string.IsNullOrEmpty(brand)) { return null; } //if(brand == "罗技") //{ // return new LogitechMouse(); //} //else if (brand == "雷蛇") //{ // return new RazeMouse(); //} //else //{ // return null; //} //反射鼠标实体 return Activator.CreateInstance(Type.GetType(brand)) as IMouse; } } class Program { static void Main(string[] args) { //创建工厂 MouseFactory factory = new MouseFactory(); //通过工厂生产实体 //IMouse mouseA = factory.CreateMouse("罗技"); //IMouse mouseB = factory.CreateMouse("雷蛇"); IMouse mouseA = factory.CreateMouse(MouseBrandConst.Logitech); IMouse mouseB = factory.CreateMouse(MouseBrandConst.Raze); Console.WriteLine($"MouseA的品牌是:{mouseA.GetBrand()}"); Console.WriteLine($"MouseB的品牌是:{mouseB.GetBrand()}"); Console.ReadKey(); } }