C#设计模式之工厂方法模式
一、引言
在前面我们介绍到关于简单工厂设计模式的一些讲解。那么本篇章主要讲解工厂方法模式。但从字面上来看,简单工厂模式和工厂模式都是基于工厂思想的。那么两者之间自然存在着一定的相似。
先来回顾一下简单工厂模式的原理:
由上图可知,简单工厂模式中,
其中共有七个(或更多)的产品,这些产品符合一定的标准规范,及所有产品都是继承同一个类。
这样可以使所有产品具有同一类型的模板。实现基本类似的功能。
工厂类Operate中有一个switch语句,这个选择语句可以根据用户的指定来实例化7个(或更多)产品中的一个。其余没有选择的产品不会实例化,防止资源浪费。
所以简单工厂模式的核心就是选择性实例化对象。如下:
public 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;
}
case "sqr":
{
oper = new OperationSqr(); //返回产品(平方类的对象)
break;
}
case "sqrt":
{
oper = new OperationSqrt(); //返回产品(开方类的对象)
break;
}
case "+/-":
{
oper = new OperationReverse();//返回产品(相反数类的对象)
break;
}
}
return oper; //将最终选择的返回
}
}
那么工厂方法类和简单工厂类又什么区别呢?下面我们正式介绍
二、工厂方法模式和简单工厂模式不同
工厂方法模式将简单工厂模式中的switch语句中的分支全部变成了工厂子类,让其新建产品放到具体工厂子类中去。这个概念有点像是,将不同的产品放到不同的子工厂里去生成。然后通过选择哪个子工厂即选择了相应的产品了。例如一个家电工厂分为洗衣机工厂分部、冰箱工厂分部、热水器工厂分部。那么用户在选择热水器的话,就必须指定热水器工厂分部,让其进行热水器的生产。这样做能够将责任细化。而简单工厂模式中,因为只有一个工厂,所以无论什么产品都在同一个工厂中生产。所以工厂方法模式比简单工厂模式更加的细化,大大降低了耦合程度。
三、工厂方法模式的实现
与简单工厂模式相比,工厂方法模式主要不同点在于工厂中的选择部分。
//产品接口类
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;
}
}
class OperationSqr : Operation
{
public override double GetResult()
{
double result = 0;
result = NumberB * NumberB;
return result;
}
}
class OperationSqrt : Operation
{
public override double GetResult()
{
double result = 0;
if (NumberB < 0)
throw new Exception("负数不能开平方根。");
result = Math.Sqrt(NumberB);
return result;
}
}
class OperationReverse : Operation
{
public override double GetResult()
{
double result = 0;
result = -NumberB;
return result;
}
}
//工厂接口类,工厂规范
/// <summary>
/// 工厂标准规范/"接口",所有的子工厂必须继承它以便统一规范
/// </summary>
public abstract class Factory
{
public abstract Operation CreateOperation();
}
//具体子工厂类
public class FactoryAdd:Factory
{
public override Operation CreateOperation()
{
return new OperationAdd();
}
}
public class FactorySub : Factory
{
public override Operation CreateOperation()
{
return new OperationSub();
}
}
public class FactoryMul : Factory
{
public override Operation CreateOperation()
{
return new OperationMul();
}
}
public class FactoryDiv : Factory
{
public override Operation CreateOperation()
{
return new OperationDiv();
}
}
public class FactorySqr : Factory
{
public override Operation CreateOperation()
{
return new OperationSqr();
}
}
public class FactorySqrt : Factory
{
public override Operation CreateOperation()
{
return new OperationSqrt();
}
}
public class FactoryReverse : Factory
{
public override Operation CreateOperation()
{
return new OperationReverse();
}
}
//用户端
/*简单工厂的特点:
* 只有一个工厂
* 一个工厂只生产一种产品
*/
/*工厂方法的特点
* 有多个子工厂
* 每个工厂各司其职,只生产属于自己的产品
* 将不同的产品划分,有较低的耦合度
*/
static void Main(string[] args)
{
try
{
Console.Write("请输入数字A:");
string strNumberA = Console.ReadLine();
Console.Write("请选择运算符号(+、-、*、/):");
string strOperate = Console.ReadLine();
Console.Write("请输入数字B:");
string strNumberB = Console.ReadLine();
string strResult = "";
Factory fac = null;
switch (strOperate) //通过选择分支选择具体的子工厂
{
case "+":
fac = new FactoryAdd(); //返回产品
break;
case "-":
fac = new FactorySub(); //返回产品
break;
case "*":
fac = new FactoryMul(); //返回产品
break;
case "/":
fac = new FactoryDiv(); //返回产品
break;
case "sqr":
fac = new FactorySqr(); //返回产品
break;
case "sqrt":
fac = new FactorySqrt(); //返回产品
break;
case "+/-":
fac = new FactoryReverse();//返回产品
break;
}
Operation oper=fac.CreateOperation(); //调用子工厂的方法来进行创建产品类
oper.NumberA = Convert.ToDouble(strNumberA); //将选好的类的数值A赋值
oper.NumberB = Convert.ToDouble(strNumberB); //将选好的类的数值B赋值
strResult = oper.GetResult().ToString(); //访问选好类中的方法返回操作结果
Console.WriteLine("结果是:" + strResult);
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("您的输入有错:" + ex.Message);
}
四、总结
综上所述,工厂方法模式与简单工厂模式之间的区别就是。工厂方法模式中存在着多个子工厂,由子工厂生产具体的产品。每个工厂各司其职,不混淆,耦合性地。方便扩展。
工厂方法模式的内部关系为: