工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
1.在简单工厂中,客户端没有对具体产品有依赖,只是发出一个参数,工厂生产它要的结果。但是这样一来工厂就必须有逻辑判断,如果我们要扩展相应功能,那么工厂内部需要修改,新的功能也需要添加。这样的程序扩展性比较差,要加一些新功能的话,原先的代码也得改,这样不好。
2.在工厂方法中,我们可以直接添加各种功能,也就是各种具体的工厂,拓展性很好的。因为接口工厂部分不用动,通过这个统一的接口,我们实现出不同的具体工厂,然后用统一的方法在不同的工厂中实现不同的方法。
3.至于到底实现出哪个工厂,这个转为客户端来判断。因为判断早晚都得有,放在比较简单而且经常改动的客户端那部分还是可以接受的。
接口工厂:
//定义工厂接口,使之后所有的具体工厂都可以用一个统一的方法实现不同的效果 interface IFactory { Operation CreateOperation(); }
具体工厂:
//这些不同的工厂类继承于接口工厂 //接口工厂的方法在这些类中返回不同的实例 class AddFactory : IFactory { public Operation CreateOperation() { return new OperationAdd(); } } class SubFactory :IFactory { public Operation CreateOperation() { return new OperationSub (); } } class MulFactory:IFactory { public Operation CreateOperation() { return new OperationMul (); }这些工厂实现了多态,而且可以不断扩展新的
public class Operation { private double _numberA = 0; private double _numberB = 0; public double NumberA { get { return _numberA; } set { _numberA = value; } } public double NumberB { get { return _numberB; } set { _numberB = value; } } public virtual double GetResult() { double result = 0; return result; } }
//具体的各种算法类,分别定义自己的算法 class OperationAdd : Operation { public override double GetResult() { double result = 0; result = NumberA + NumberB; return result; } } class OperationSub : Operation { public override double GetResult() { double result = 0; result = NumberA - NumberB; return result; } } class OperationMul : Operation { public override double GetResult() { double result = 0; result = NumberA * NumberB; return result; } } class OperationDiv : Operation { public override double GetResult() { double result = 0; if (NumberB == 0) throw new Exception("除数不能为0."); result = NumberA / NumberB; return result; } }
这些和之前的一样
static void Main(string[] args) { //获得用户输入值和符号 Console.Write("请输入数字A: "); string strNumberA = Console.ReadLine(); Console.Write("请选择运算符号 (+ - * /):"); string strOperate = Console.ReadLine(); Console.Write("请输入数字 B: "); string strNumberB = Console.ReadLine(); //声明一个工厂 IFactory operFactory=null; //通过用户的符号参数来生成具体的工厂类 switch (strOperate) { case "+": operFactory =new AddFactory(); break; case "-": operFactory =new SubFactory(); break; case"*": operFactory=new MulFactory(); break; case "/": operFactory = new DivFactory(); break; } //用同一个方法,在不同的工厂内实例化不同的方法 Operation oper = operFactory.CreateOperation(); oper.NumberA = Convert.ToDouble (strNumberA ); oper.NumberB = Convert.ToDouble (strNumberB ); double result = oper.GetResult(); Console.WriteLine("结果是:" + result); Console.ReadLine(); } }
还用上篇博客中吃水果的例子。
简单工厂是我(客户端)通过喊母亲(工厂),递给我不同的水果(根据要求实例化)。
但是随着我的胃口越来越大,想吃各种各样的水果,那么母亲就得买回一篮子一篮子各种不同的水果,而且她得和我们同步水果的名字,得学习认识新的水果。有一天,我们亲爱的母亲也烦了,我们的要求一变她就得学新的东西,而且还得买回来。终于母亲生气了,后果很严重。因为累了,时不时歇一歇,因为东西多,时不时弄错一些。
伟大的工厂方法是一个技术的转折。
我们知道母亲累了,所以母亲就做一件事情,执行一个动作就好了,帮我们去水果就好了。
那么水果哪里来?
当然是我们自己整了,不过是叫人弄。因为我们知道自己想吃什么,所以就自己点一种水果外卖送到家门口。世界上每出现一种新的水果生产者,我们就记一个电话(case语句),打个电话,具体的水果商开车到我家,我的妈妈每次都只是取水果,但是每次取得都不一样(完美实现了多态~)。
有了工厂方法,世界再次美好了,妈妈再也不用劳累了。
——本学习总结参考书籍为《大话设计模式》作者:程杰