设计模式--简单工厂模式

最近又在看程杰的《大话设计模式》这本书,这真的是我超级喜欢的一本书,里面的内容很精彩,学习之余,将书中的内容整理出来,另外加上了一些自己的理解,方便日后自己回顾并同时希望本笔记可以对各位编程者有所帮助,相关技术上博主理解如有偏颇,还请指正。


简单工厂模式是项目开发中最常用也是最重要的一种设计模式,几乎在所有的项目开发中都会用到。可能你还不知道简单工厂模式是什么,但也许这种设计思想你早就在实际项目开发中接触过了。

接下来就来看看简单工厂模式到底是什么。

 

首先大家想一个问题,如果叫你实现一个计算器控制台程序,要求输入两个数和运算符号,得到运算结果,你会怎么做?

初级版本:

class Program  
{  
    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 = "";  
  
            switch (strOperate)  
            {  
                case "+":  
                    strResult = Convert.ToString(Convert.ToDouble(strNumberA) + Convert.ToDouble(strNumberB));  
                    break;  
                case "-":  
                    strResult = Convert.ToString(Convert.ToDouble(strNumberA) - Convert.ToDouble(strNumberB));  
                    break;  
                case "*":  
                    strResult = Convert.ToString(Convert.ToDouble(strNumberA) * Convert.ToDouble(strNumberB));  
                    break;  
                case "/":  
                    if (strNumberB != "0")  
                        strResult = Convert.ToString(Convert.ToDouble(strNumberA) / Convert.ToDouble(strNumberB));  
                    else  
                        strResult = "除数不能为0";  
                    break;  
            }  
  
            Console.WriteLine("结果是:" + strResult);  
              
            Console.ReadLine();  
        }  
        catch (Exception ex)  
        {  
            Console.WriteLine("您的输入有错:" + ex.Message);  
        }  
    }  
}  

能写出以上代码已经不错了,至少已经实现了目前的计算器功能。但是这个代码是面向过程而非面向对象的,只能满足当前的需求,程序不容易扩展和复用和维护。

试想,假如我现在又让你写一个Windows的计算器,你在原来的代码上能改吗?显然,你还需要再重新写一个程序。但是Windows计算器和控制台计算器只是在显示上不同,业务的逻辑处理是相同的。所以说你之前面向过程的程序是有弊端的:很难进行二次开发!

所以,接下来的改进之处就是利用面向对象的封装特性,将业务逻辑与界面逻辑分开,使其耦合度下降,达到复用的目的;

升级版本:

界面逻辑部分:

class Program  
    {  
        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 = "";  
                strResult = Convert.ToString(Operation.GetResult(Convert.ToDouble(strNumberA),Convert.ToDouble(strNumberB),strOperate));  
                Console.WriteLine("结果是:" + strResult);  
                Console.ReadLine();  
            }  
            catch (Exception ex)  
            {  
                Console.WriteLine("您的输入有错:" + ex.Message);  
            }  
        }  
    }  

业务逻辑部分:

 public class Operation  
    {  
        public static double GetResult(double numberA,double numberB,string operate)  
        {  
            double result = 0d;  
            switch (operate)  
            {  
                case "+":  
                    result = numberA + numberB;  
                    break;  
                case "-":  
                    result = numberA - numberB;  
                    break;  
                case "*":  
                    result = numberA * numberB;  
                    break;  
                case "/":  
                    result = numberA / numberB;  
                    break;  
            }  
            return result;  
        }  
    }  

以上版本代码,把业务和界面分离,如果此时再让写一个Windows应用程序的计算器,就可以复用Operation运算类了,而且不单是Windows版,Web版、手机版、Pad版都可以复用。

接下来,假如我现在希望再增加一个开根(sqrt)运算,要怎么改?你可能会想,直接在Operation里添加一个分支运算就好了。但实际项目开发中,业务逻辑通常都会很复杂,要做很多的事,不只是做个加减法这么简单。所以,我们应该保证修改某一种类型业务而不会影响其他的。比如在这里,我们应该将加减乘除等运算分离,修改其中一个而不影响另外几个,增加运算代码也不影响其他代码,这体现了面向对象的继承和多态特性。

 高级版本:

   /// <summary>  
   /// 运算类  
   /// </summary>  
   class Operation  
   {  
       private double _numberA = 0;  
       private double _numberB = 0;  
         
       /// <summary>  
       /// 数字A  
       /// </summary>  
       public double NumberA  
       {  
           get{ return _numberA; }  
           set{ _numberA = value;}  
       }  
  
       /// <summary>  
       /// 数字B  
       /// </summary>  
       public double NumberB  
       {  
           get{ return _numberB; }  
           set{ _numberB = value; }  
       }  
  
       /// <summary>  
       /// 得到运算结果  
       /// </summary>  
       /// <returns></returns>  
       public virtual double GetResult()  
       {  
           double result = 0;   
           return result;  
       }       
   }  
</pre><pre name="code" class="csharp">    ///summary
    /// 加法类  
    /// </summary>  
    class OperationAdd : Operation  
    {  
        public override double GetResult()  
        {  
            double result = 0;   
            result = NumberA + NumberB;  
            return result;  
        }  
    }  
    /// <summary>  
    /// 减法类  
    /// </summary>  
    class OperationSub : Operation  
    {  
       public override double GetResult()  
        {  
            double result = 0;  
            result = NumberA - NumberB;  
            return result;  
        }  
    }  
    /// <summary>  
    /// 乘法类  
    /// </summary>  
    class OperationMul : Operation  
    {  
        public override double GetResult()  
        {  
            double result = 0;  
            result = NumberA * NumberB;  
            return result;  
        }  
    }  
    /// <summary>  
    /// 乘法类  
    /// </summary>  
    class OperationMul : Operation  
    {  
        public override double GetResult()  
        {  
            double result = 0;  
            result = NumberA * NumberB;  
            return result;  
        }  
    }  

以上,首先是一个运算类,它有两个Number属性和一个虚方法GetResult(),加减乘除都是运算类的子类,继承了它并重写了GetResult()方法,这样,修改某一个运算就不会影响其他的运算了。

那么,如何让计算器知道我们需要用哪一个方法呢?现在的问题其实就是如何去实例化对象,我们用一个单独的类来做这个创造实例的过程,这就是工厂类,

 /// <summary>  
 /// 运算类工厂  
 /// </summary>  
 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;  
                 }  
          }  
         return oper;  
     }  
 }  

这样,只要输入运算符号,工厂就实例化出合适的对象,通过多态,返回父类的方法实现了计算器结果,这种方法就是简单工厂模式。

Operation oper;  
oper = OperationFactory.createOperate("+");  
oper.NumberA = 1;  
oper.NumberB = 2;  
double result = oper.GetResult();


简单工厂模式包含以下角色和职责:

工厂(Creator):简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。

抽象产品(Product):简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

具体产品(Concrete Product):是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

 

最后我们再总结一下简单工厂模式的特性

1.产品业务逻辑与界面逻辑分开;

2.将产品细分,不同种类的产品子类都有一个共同的抽象父类,重写了父类的方法,各种产品互不干涉,修改某一个不会影响其他,并实现可可扩展;

3.增加一个工厂类Factory,该类负责根据条件选择实例化哪一种产品,并创造实例;

4.如果需要增加运算,一方面需要增加产品子类,另一方面需要修改工厂类。

 




好了,以上便是简单工厂模式的相关内容。

 

 

 

 

你可能感兴趣的:(设计模式,面向对象,简单工厂模式,工厂模式,工厂类)