设计模式 -- 简单工厂
工厂模式分为:简单工厂,工厂方法,抽象工厂三种模式,严格来说简单工厂不算是一种模式,反而比较像是一种编程习惯,由于比较常用,有些开发人员也把简单工厂看成是工厂模式。
首先,所有工厂模式都是用来封装对象的创建的,这样一来,我们的对象创建就能“隐蔽”(你看不见new的过程)的进行,同时这也使得对象之间的依赖关系大大降低,也就符合了我们“低耦合”的设计原则。
今天我们来看一下“简单工厂”这个非常好的编程习惯。
1、什么是“简单工厂”?
简单工厂说白了就是把创建对象的过程分离出来。比如说我们实现一个能够进行简单加减乘除的计算器,那么你肯动能想到要有一个计算类,这个计算类应该有两个操作数和一个操作符,然后有加,减,乘,除四个方法,或者你只有一个方法,这个方法内部根据操作符的不同来做不同的操作。这没错,但是有没有想过这样实现很不好呢?比如说我现在要实现乘方的操作,或者又加上算术平方根操作等等,是不是要修改我们已经写好的计算类呢?如果你要修改你就违背了“对修改封闭”的原则。或许你会说,我可以用继承来扩展原来的计算类,还记不记得我们之前写的一些关于继承的“黑暗面”呢?呵呵,用工厂来解决这个问题吧,会让你眼前一亮的。
2、简单工厂如何实现?
什么是工厂呢?工厂就是生产产品的地方。那么简单工厂就是这样的一个类,这个类可以根据不同的要求创建不同的类对象。那么说明白了,我们首先要创建一个工厂类,这个工厂里要写一个方法createObject(参数),这个方法就根据参数的不同来“生产”不同的对象。
3、具体示例
有两个很不错的例子,拿来和大家分享,一个就是我们刚刚说的简单计算器,一个呢是比萨店的例子。很简单,耐心看完,简单工厂就学会了。
首先看一下简单计算器的类图:
代码:
//工厂类 class OperationFactory { public static Operation createOperate(string operate) { Operation oper = null; switch(operate) { case "+": { oper = new OperationAdd(); break; } case "-": { oper = new OperationSub(); break; } case "*": { oper = new OperationMul(); break; } case "/": { oper = new OperationDiv(); break; } } return oper; } }
//计算类 class Operation { public double _numberLeft; public double _numberRight; public double numberLeft { get { return _numberLeft;} set { _numberLeft = value;} } public double numberRight { get { return _numberRight;} set { _numberRight = value;} } public virtual double GetResult() { double result = 0; return result; } } class OperationDiv:Operation { public override double GetResult() { double result = 0; if (numberRight == 0) { throw new Exception("除数不能是0"); } result = numberLeft / numberRight; return result; } } class OperationMul:Operation { public override double GetResult() { double result = 0; result = numberLeft * numberRight; return result; } } class OperationSub:Operation { public override double GetResult() { double result = 0; result = numberLeft - numberRight; return result; } } class OperationAdd:Operation { public override double GetResult() { double result = 0; result = _numberLeft + _numberRight; return result; } }
比萨店 类图:
代码:
//pizza工厂 public class SimplePizzaFactory { public Pizza createPizza(string type) { Pizza pizza = null; if (type == "cheese") { pizza = new CheesePizza(); } else if(type == "clam") { pizza = new ClamPizza(); } else if (type == "pepperoni") { pizza = new PepperoniPizza(); } else if (type == "veggie") { pizza = new VeggiePizza(); } return pizza; } }
//pizza类 public abstract class Pizza { public void prepare() { Console.WriteLine("pizza is being prepared"); } public void bake() { Console.WriteLine("pizza is being baken"); } public void cut() { Console.WriteLine("pizza is being cut"); } public void box() { Console.WriteLine("pizza is being boxed"); } } //蔬菜Pizza public class VeggiePizza:Pizza { public VeggiePizza() { Console.WriteLine("Veggie Pizza"); } } //奶酪Pizza public class CheesePizza:Pizza { public CheesePizza() { Console.WriteLine("CheesePizza"); } } //蛤蛎Pizza public class ClamPizza:Pizza { public ClamPizza() { Console.WriteLine("Clam Pizza"); } } //意大利辣香肠Pizza public class PepperoniPizza:Pizza { public PepperoniPizza() { Console.WriteLine("Pepperoni Pizza"); } }
//Pizza店 class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) { this.factory = factory; } public Pizza orderPizza(string pizzatype) { Pizza pizza = factory.createPizza(pizzatype); if (pizza!= null) { pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } return null; } }
不难看出,这两个例子中都把创建具体类对象的代码从一个基类中分离出来放在一个创建对象的工厂里,这样做不仅仅是隐藏了对象的创建,也很大程度上降低了类之间的耦合。