1.工厂模式介绍
上一篇我们知道了简单工厂的缺点是:当我们添加一个新的产品时需要修改工厂类,这样就违背了开闭原则。工厂模式就是为了解决这一缺陷而出现的,解决的方法是把创建具体实例的任务放在了工厂的子类中,工厂只提供了创建实例的的接口,还以上一篇中的生产鼠标为例:
鼠标类:
//鼠标抽象类 public abstract class Mouse { public abstract void Print(); } //戴尔鼠标 public class DellMouse : Mouse { public override void Print() { Console.WriteLine("生产了一个Dell鼠标!"); } } //惠普鼠标 public class HpMouse : Mouse { public override void Print() { Console.WriteLine("生产了一个惠普鼠标!"); } }
工厂类只提供生产鼠标的抽象方法(或者接口),其子类生产具体的产品,如戴尔鼠标工厂继承于鼠标工厂,它只生产戴尔鼠标;惠普鼠标工厂只生产惠普鼠标,代码如下:
/// <summary> /// 鼠标工厂抽象类 /// </summary> public abstract class MouseFactory { public abstract Mouse CreateMouse(); } //戴尔鼠标工厂 public class DellMouseFactroy : MouseFactory { public override Mouse CreateMouse() { return new DellMouse();//在具体的工厂中实例化产品 } } //惠普鼠标工厂 public class HpMouseFactory : MouseFactory { public override Mouse CreateMouse() { return new HpMouse();//在具体的工厂中实例化产品 } }
客户端代码:
static void Main(string[] args) { //生产一个戴尔鼠标 MouseFactory dellMouseFactory = new DellMouseFactroy(); Mouse dellMouse= dellMouseFactory.CreateMouse(); dellMouse.Print(); //生产一个惠普鼠标 MouseFactory hpMouseFactory = new HpMouseFactory(); Mouse hpMouse = hpMouseFactory.CreateMouse(); hpMouse.Print(); Console.ReadKey(); }
运行程序,结果如下:
在上边的例子我们可以看出:客户端要生产一个具体产品时,首先要获取这个产品对应的具体工厂实例,然后通过具体工厂来实例化产品。如果我们想生产华硕鼠标的话,要添加一个华硕鼠标工厂类(AsusMouseFactory)和华硕鼠标类(AsusMouse),然后在客户端通过以下代码来生产华硕鼠标:
MouseFactory asusMouseFactroy=new AsusMouseFactroy(); asusMouseFactory.CreateMouse();
通过工厂模式添加新产品是只有添加的操作,而不会去修改以前的代码,符合开闭原则。
2.小结
上边代码的类图:
工厂模式的优点:
工厂模式有效地解决了添加新产品必须要修改工厂类代码的问题,符合设计原则中的开闭原则。
工厂模式的缺点:
工厂模式的本质是将具体实例的创建工作放在了具体子类工厂中进行,这造成一个新的问题:将选择实例类型的任务交给了客户端,如我们想生产一个戴尔鼠标,就必须在客户端new一个戴尔鼠标工厂。想象下如果我们new了100个戴尔鼠标工厂,这是要换到惠普鼠标怎么办?只能把new DellMouseFactory一个一个地替换成new HpMouseFactory。所以简单工厂和工厂模式都不是完美的,我们应该根据具体的情况来选择。