工厂模式在一些设计模式的书中分为简单工厂模式,工厂方法模式和抽象工厂模式三类。也有把工厂方法模式划分到抽象工厂模式的,认为工厂方法是抽象工厂模式的特例的一种,就是只有一个要实现的产品接口。
就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。首先看下关系图
举个获取鼠标信息例子,我们有个例子。
public class LenoveMouse : IMouse { public string GetMouseInfo() { return "联想品牌鼠标"; } }
public string GetMouseInfo() { return "联想品牌鼠标"; }
3.惠普鼠标实现类
public class HPMouse : IMouse { public string GetMouseInfo() { return "惠普品牌鼠标"; } }
public class MouseFactory { /// <param name="type">0 代码惠普鼠标 1 代码联想鼠标</param> /// <returns></returns> public IMouse GetMouse(int type) { if (type == 0) { return new HPMouse(); } else if (type == 1) { return new LenoveMouse(); } else { Console.WriteLine("请输入正确类型!"); return null; } } }
class Program { static void Main(string[] args) { MouseFactory mouseFactory = new MouseFactory(); string mouseInfo1 = mouseFactory.GetMouse(0).GetMouseInfo(); Console.WriteLine(mouseInfo1); // 输出:惠普品牌鼠标 string mouseInfo2 = mouseFactory.GetMouse(1).GetMouseInfo(); Console.WriteLine(mouseInfo2); //输出:联想品牌鼠标 } }
是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的类型出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。关系图:
工厂类修改
public class MouseFactory { public IMouse GetHPMouse() { return new HPMouse(); } public IMouse GetMouse() { return new LenoveMouse(); } }
控制台调用修改
class Program { static void Main(string[] args) { MouseFactory mouseFactory = new MouseFactory(); string mouseInfo1 = mouseFactory.GetHPMouse().GetMouseInfo(); //输出惠普鼠标品牌 Console.WriteLine(mouseInfo1); string mouseInfo2 = mouseFactory.GetLenoveMouse().GetMouseInfo(); //输出联想鼠标品牌 Console.WriteLine(mouseInfo2); Console.ReadLine(); } }
将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。
public class MouseFactory { public static IMouse GetHPMouse() { return new HPMouse(); } public static IMouse GetLenoveMouse() { return new LenoveMouse(); } }
控制台调用
class Program { static void Main(string[] args) { string mouseInfo1 = MouseFactory.GetHPMouse().GetMouseInfo(); //输出惠普鼠标品牌 Console.WriteLine(mouseInfo1); string mouseInfo2 = MouseFactory.GetLenoveMouse().GetMouseInfo(); //输出联想鼠标品牌 Console.WriteLine(mouseInfo2); Console.ReadLine(); } }
简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改。假如增加其他品牌鼠标,工厂类需要修改,如何解决?就用到工厂方法模式,创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
增加Factory接口
public interface Factory { /// <summary> /// 获取鼠标工厂 /// </summary> /// <returns></returns> IMouse GetMouseFactory(); }
添加惠普鼠标工厂实现类
public class HPMouseFactory:Factory { public IMouse GetMouseFactory() { return new HPMouse(); } }
添加联想鼠标工厂实现类
public class LenoveMouseFactory : Factory { public IMouse GetMouseFactory() { return new LenoveMouse(); } }
控制台调用
在这里插入代码片
class Program { static void Main(string[] args) { //实例化惠普鼠标工厂 Factory factory = new HPMouseFactory(); string mouseInfo1 = factory.GetMouseFactory().GetMouseInfo(); //输出惠普鼠标品牌 Console.WriteLine(mouseInfo1); //实例化联想鼠标工厂 Factory factory2 = new LenoveMouseFactory(); string mouseInfo2 = factory2.GetMouseFactory().GetMouseInfo(); //输出联想鼠标品牌 Console.WriteLine(mouseInfo2); Console.ReadLine(); } } 工厂方法模式中我们把生成产品类的时间延迟,就是通过对应的工厂类来生成对应的产品类,在这里我们就可以实现“开发-封闭”原则,无论加多少产品类,我们都不用修改原来类中的代码,而是通过增加工厂类来实现。但是这还是有缺点的,如果添加键盘产品,就需要添加键盘工厂类。假如我们要实现的产品接口不止一个,也就是有多个产品接口,不同产品接口有对应的产品族。什么是产品族呢?简单的理解就是,不同厂家的不仅有鼠标,还有键盘,音响,笔记本可以组成一个产品族。对于这种情况我们可以采用抽象工厂模式。
最后我们新增一个键盘产品类说明抽象工厂模式
public class LenoveMouse : IMouse { public string GetMouseInfo() { return "联想品牌鼠标"; } }
public string GetMouseInfo() { return "联想品牌鼠标"; }
3.惠普鼠标实现类
public class HPMouse : IMouse { public string GetMouseInfo() { return "惠普品牌鼠标"; } }
4.创建键盘接口类
public interface IKeyboard { string GetKeyboardInfo(); }
5.创建惠普键盘实现类
public class HPKeyboard : IKeyboard { public string GetKeyboardInfo() { return "惠普键盘"; } }
6.创建联想键盘实现类
public class LenoveKeyboard : IKeyboard { public string GetKeyboardInfo() { return "联想键盘"; } }
7.创建工厂接口类提供获取鼠标鼠标和键盘接口
public interface Factory { /// <summary> /// 获取鼠标工厂 /// </summary> /// <returns></returns> IMouse GetMouseFactory(); /// <summary> /// 获取键盘工厂 /// </summary> /// <returns></returns> IKeyboard GetKeyboardFactory(); }
8.创建联想工厂实现类
public class LenoveFactory : Factory { public IKeyboard GetKeyboardFactory() { return new LenoveKeyboard(); } public IMouse GetMouseFactory() { return new LenoveMouse(); } }
9.创建惠普工厂实现类型
public class HPFactory:Factory { public IKeyboard GetKeyboardFactory() { return new HPKeyboard(); } public IMouse GetMouseFactory() { return new HPMouse(); } }
控制台调用
class Program { static void Main(string[] args) { //实例化惠普鼠标工厂 Factory factory = new HPFactory(); string mouseInfo1 = factory.GetMouseFactory().GetMouseInfo(); string keyboard1 = factory.GetKeyboardFactory().GetKeyboardInfo(); //输出惠普鼠标品牌 Console.WriteLine(mouseInfo1); //输出惠普键盘 Console.WriteLine(keyboard1); //实例化联想鼠标工厂 Factory factory2 = new LenoveFactory(); string mouseInfo2 = factory2.GetMouseFactory().GetMouseInfo(); //输出联想鼠标品牌 Console.WriteLine(mouseInfo2); //输出联想键盘品牌 string keyboard2= factory2.GetKeyboardFactory().GetKeyboardInfo(); Console.ReadLine(); } }
抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。我们在使用中要注意使用抽象工厂模式的条件。
无论是工厂模式增加代码复制度,有没有一种办法,不需要创建工厂,也能解决代码以后变动修改少方法。答案是有的,通过(ioc)控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,(di)依赖被注入到对象中。