咱们先来看看一个简单的计算机案例(一个控制台应用程序):
Operation是一个运算类,加减乘除方法继承于Operation。
- /// <summary>
- /// 运算类
- /// </summary>
- abstract public class Operation
- {
- public double NumberA { get; set; }
- public double NumberB { get; set; }
- public abstract double GetResult();
- }
- /// <summary>
- /// 加法类
- /// </summary>
- public class OperationAdd:Operation
- {
- public override double GetResult()
- {
- return base.NumberA + base.NumberB;
- }
- }
减法,乘法,除法类似,在此不列出。
在这里就有一个问题了,我们怎么让程序知道我们到底是要执行哪一种运算呢?也就是如何去实例化对象的问题。
在这里到底要实例化谁,将来会不会增加这实例化的对象,比如增加开根运算,这是很容易变化的地方,
应该考虑用一个单独的类做这个创造实例的过程,这就是工厂。下面我们就引入简单工厂:
- public class OperationFaction
- {
- public static Operation createOperation(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;
- }
- }
工厂方法通常是一个静态方法,因此又叫静态工厂方法模式,这个方法返回的类型为通用的父类类型,但是new的是具体的子类类型。
在这里我们只需要输入运算符号,工厂就实例化出合适的对象,通过多态,返回的父类的方式实现了计算器的计算。
客户端代码:
- class Program
- {
- static void Main(string[] args)
- {
- Operation oper = null;
- oper = OperationFaction.createOperation("+");
- oper.NumberA = 10;
- oper.NumberB = 12;
- double result = oper.GetResult();
- Console.WriteLine("运行结果为:"+result);
- }
- }
当我们需要增加各种运算,比如平方根,立方根等的时候,我们只需要添加相应的运算子类,和在工厂类中添加一个分支就可以了。
我们再来看看总体的UML图:
下面我们再来详细的分析一下简单工厂:
优点:
简单工厂中“工厂类”是整个模式的关键,包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.
通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。
而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点:
简单工厂不符合开放-封闭原则,简单工厂在对每一次扩展时都要更改工厂类,这就是对修改开放了,这就不符合开闭原则。
当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.
这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展也非常不利;
工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中,这样对于维护非常不方便。
简单工厂应用场景:
工厂类负责创建的对象比较少;客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。