咱们先来看看一个简单的计算机案例(一个控制台应用程序):
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图:
下面我们再来详细的分析一下简单工厂:
优点:
简单工厂中“工厂类”是整个模式的关键,包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.
通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。
而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点:
简单工厂不符合开放-封闭原则,简单工厂在对每一次扩展时都要更改工厂类,这就是对修改开放了,这就不符合开闭原则。
当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.
这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展也非常不利;
工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中,这样对于维护非常不方便。
简单工厂应用场景:
工厂类负责创建的对象比较少;客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。
本教程参考“大话设计模式”,作者:程杰。