原文地址:http://blog.csdn.net/lilysara/article/details/66975628
工厂模式
工厂模式是创建模式,主要是为创建对象提供过渡接口 ,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂模式在《深入浅出设计模式》和《大话设计模式》中分为三类:
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Factory)
- 抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具有一般性。
我刚开始看着《大话设计模式》学习,抽象工厂还没看到,所以这一篇就先记一下前两种,后面看到了再更新。。。
简单工厂模式
简单工厂模式又称为静态工厂方法模式,它其实不是23种设计模式之一,只是工厂模式的简单版本(嗯,看名字就知道了)。我的理解,简单地说,它就是用一个单独的类来进行创建实例这个过程。
简单工厂模式的组成有:
- 工厂类角色,它是这个模式的核心,包含一定的判断逻辑。
- 抽象产品角色,它是具体产品所继承的父类或实现的接口。
- 具体产品角色,这才是使用模式要创建的具体实例的类。
类图如下:
借《大话设计模式》中的例子,展示一下模式的应用。
语言:C#
编译环境:Mac MonoDevelop
要求:实现一个计算器的功能。
计算器有不同的运算符(+、-、*、/),这些运算符都有一个共同的特点:使用两个操作数,然后得出运算结果,因此我们可以写出运算基类。
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;
}
}
乘法类、除法类同理可以实现。
接下来是关键的工厂类,根据传入的参数的不同,动态地决定实例化哪个类。
public class OperationFactory
{
public static Operation createOperate(string operate)
{
Operation oper = null;
switch (operate) {
case "+":
oper = new OperationAdd ();
break;
case "-":
oper = new OperationSub ();
break;
}
return oper;
}
}
最后是客户端的实现。
Operation oper;
oper = OperationFactory.createOperate ("+");
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult ();
Console.WriteLine ("result = " + result.ToString());
这样就完成了简单工厂模式,如果后面要增加其他运算,比如乘方、正弦等,只需要增加相应的运算子类,然后在工厂类里增加判断即可。
写到这里,大家大概可以看出简单工厂的优缺点了。
优点:
工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅”消费”产品。简单工厂模式通过这种做法实现了对责任的分割。
缺点:
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();
}
}
接下来是客户端的实现:
IFactory operFactory = new AddFactory();
Operation oper = operFactory.CreateOperation ();
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult ();
Console.WriteLine ("result = " + result.ToString());
工厂方法模式克服了简单工厂违背开闭原则的缺点,又保持了封装对象创建过程的优点。但缺点是每加一个产品,就需要增加一个产品工厂的类。简单工厂的判断是在工厂类里,工厂方法模式其实是把判断移到了客户端。不过,C#的反射机制可以解决分支判断的问题。嗯,后面再说。