设计模式培训之二:简单工厂、工厂方法

查看本人文章索引请通过http://www.cnblogs.com/seesea125/archive/2012/04/17/2453256.html

一、简单工厂和工厂方法定义:

简单工厂模式是由一个工厂类根据参数来决定创立出哪一种产品类的实例。

工厂方法模式通过调用不同的方法返回需要的类,而不是去实例化具体的类。 对实例创建进行了包装。 工厂方法是一组方法, 他们针对不同条件返回不同的类实例,这些类一般有共同的父类。

工厂方法模式实施一种按需分配的策略, 即传入参数进行选择, 工厂方法根据参数进行选择,返回具体的实例。

 

二、实例讲解:实现加减乘除

程序需求:

处理两个数的+,-,*,/等运算

 

1. 是面向过程的实现方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
string  strResult = "" ;
             switch  (Operate)
             {
                 case  "+" :
                     strResult = Convert.toString(Convert.ToDouble(NumA) + Convert.ToDouble(NumB));
                     break ;
                 case  "-" :
                     strResult = Convert.toString(Convert.ToDouble(NumA) - Convert.ToDouble(NumB));
                     break ;
                 case  "*" :
                     strResult = Convert.toString(Convert.ToDouble(NumA) * Convert.ToDouble(NumB));
                     break ;
                 case  "/" :
                     if  (NumB != 0)
                     {
                         strResult = Convert.toString(Convert.ToDouble(NumA) + Convert.ToDouble(NumB));
                     }
                     else
                     {
                         strResult = "除数不能为0" ;
                     }
                     break ;
             }

当增加需求时,例如:增加开方运算,这时我们需要更改上面switch的代码。如果再增加需求,还要更改switch代码。这样的代码很难维护。

健壮的设计应该是易扩展,不修改原有代码(或尽量减少修改原有代码)。

应对变化的运算方式,简单工厂就是一个很简单,好用的模式,下面是简单工厂的实现

 

2. 用简单工厂实现:

ULM图:

sclip_image002

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public  abstract  class  Operation
{
     public  double  NumA { get ; set ; }
     public  double  NumB { get ; set ; }
     public  abstract  double  GetResult();
}
 
public  class  OperationAdd : Operation
{
     public  override  double  GetResult()
     {
         return  NumA + NumB;
     }
}
 
public  class  OperationSub : Operation
{
     public  override  double  GetResult()
     {
         return  NumA - NumB;
     }
}

工厂类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public  class  Factory
{
     public  Operation Create( string  ope)
     {
         Operation operation= null ;
         switch (ope)
         {
         case  "+" :
         operation= new  OperationAdd();
         break ;
         case  "-" :
         operation= new  OperationSub();
         break ;
         }
         return  operation;
     }
}

 

客户端调用:

1
2
3
4
5
6
Operation oper;
 
oper= new  Factory().Create( "+" );
oper.NumA=1;
oper.NumB=2;
double  result=oper.GetResult();

这时在客户端代码就没有switch代码,现在的switch代码也没有运算逻辑。运算逻辑在GetResult()方法中。

当再有新需求时,我就可以增加子类(继承自Operation),在子类的GetResult方法中设置运算规则。现在只需在switch中增加一个case返回增加子类实例的代码。

简单工厂是一个不完美的模式,因为它还是修改了switch代码。

 

3 用工厂方法实现:

应对上面的需求也可以使用工厂方法模式,工厂方法使一个类的实例化延迟到其子类。

UML图:

clip_image004

复制代码
    public interface IFactory
    {
        Operation Create();
    }
    public class AddOperation : IFactory
    {
        public Operation Create()
        {
            return new OperationAdd();
        }
    }
    public class SubOperation : IFactory
    {
        public Operation Create()
        {
            return new OperationSub();
        }
    }

    public abstract class Operation
    {
        public double NumA { get; set; }
        public double NumB { get; set; }
        public abstract double GetResult();
    }
    public class OperationAdd : Operation
    {
        public override double GetResult()
        {
            return NumA + NumB;
        }
    }
    public class OperationSub : Operation
    {
        public override double GetResult()
        {
            return NumA - NumB;
        }
    }
复制代码

 

客户端:

IFactory factory = new AddOperation();
Operation oper = factory.Create();
oper.NumA = 3;
oper.NumB = 2;
double result = oper.GetResult();

 

在客户程序中,我们有效地避免了具体产品对象和应用程序之间的耦合,可是我们也看到,增加了具体工厂对象和应用程序之间的耦合。

当我们由加号操作变成减号操作时,只需要改动一处就可以了,其他地方都不用改。

IFactory factory = new SubOperation();
Operation oper = factory.Create();
oper.NumA = 3;
oper.NumB = 2;
double result = oper.GetResult();

 

当然这样的话,我们还是改动代码,这时候可以利用.NET反射机制来消除它,这样改动时,只需要改动配置文件就可以了

<appSettings>
  <add key="factoryName" value="AddOperation"></add>
</appSettings>

客户端代码:

string factoryName = ConfigurationSettings.AppSettings["factoryName"];
 IFactory factory = (IFactory)Assembly.Load("BLL").CreateInstance("BLL." + factoryName);
Operation oper = factory.Create();
oper.NumA = 3;
oper.NumB = 2;
double result = oper.GetResult();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值