首页 > 代码库 > 设计模式--简单工厂模式

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

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


简单工厂模式是项目开发中最经常使用也是最重要的一种设计模式。差点儿在全部的项目开发中都会用到。

可能你还不知道简单工厂模式是什么,但或许这样的设计思想你早就在实际项目开发中接触过了。

接下来就来看看简单工厂模式究竟是什么。

 

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

0基础版本号:

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);  
        }  
    }  
}  

能写出以上代码已经不错了。至少已经实现了眼下的计算器功能。

可是这个代码是面向过程而非面向对象的,仅仅能满足当前的需求。程序不easy扩展和复用和维护。

试想。假如我如今又让你写一个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.假设须要添加运算。一方面须要添加产品子类,还有一方面须要改动工厂类。

 




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

 

 

 

 

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