設計模式之-簡單工廠模式

前言

爲了理解和學習簡單工廠模式,咱們先看一段簡單計算器的代碼算法

 class Program
    {
        static void Main(string[] args)
        {
            Console.Write("請輸入數字A:");
            string A = Console.ReadLine();
            Console.Write("請選擇運算符號(+、-、*、/):");
            string B = Console.ReadLine();
            Console.Write("請輸入數字B:");
            string C = Console.ReadLine();
            string D = "";
            if (B == "+")
                D = Convert.ToString(Convert.ToDouble(A) + Convert.ToDouble(C));
            if (B == "-")
                D = Convert.ToString(Convert.ToDouble(A) - Convert.ToDouble(C));
            if (B == "*")
                D = Convert.ToString(Convert.ToDouble(A) * Convert.ToDouble(C));
            if (B == "/")
                D = Convert.ToString(Convert.ToDouble(A) / Convert.ToDouble(C));
            Console.WriteLine("結果是:" + D);
            Console.ReadKey();
        }
    }

以上代碼存在幾點明顯問題ide

①A、B、C、D這樣的命名很是不規範,真實項目中應該避免使用學習

②if判斷分支,讓計算機多作了三次無用功優化

③除數的時候若是用戶輸入了非正數及符號,沒有相關處理。spa

根據上述三點問題進行優化後的代碼以下:code

 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.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine("您的輸入有錯:" + ex.Message);
            }
        }
    }

就上述代碼而言,的確實現了簡單計算器的功能,可是咱們進一步思考這段代碼,若是此時 須要新作一個計算器呢?估計有不少小夥伴靈光一現,複製粘貼大法。咱們回想下古代活字印刷術的出現,對於印刷的巨大幫助。對象

⑴ 要改內容,只須要改動要改的文字,此爲可維護blog

⑵這些字並不是用完此次就無用了,之後的印刷中能夠重複使用,此乃可複用繼承

⑶若此版面內容要加字,只須要另刻字加入便可,這是可擴展get

⑷字的排列多是豎排,多是橫排,此時只須要將活字移動就可作到知足排列需求,此是靈活性好

而再活字印刷術出現以前,以上四點特性都沒法知足,要修改,必須重刻,要加字,必須重刻,要從新排列,必須重刻,印完這本後,此版已無任何可再利用價值。

面向對象的好處

★業務的封裝(讓業務邏輯與界面邏輯分開,下降耦合度)

根據上述思考,咱們將運算單獨封裝一個運算類 Operation

/// <summary>
    /// 運算類
    /// </summary>
    public class Operaion
    {
        /// <summary>
        /// 計算方法
        /// </summary>
        /// <param name="numberA">運算數</param>
        /// <param name="numberB">運算數</param>
        /// <param name="operate">符號</param>
        /// <returns>返回值</returns>
        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;
        }
    }

客戶端調用的時候調用此方法便可:

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(Operaion.GetResult(Convert.ToDouble(strNumberA),
                    Convert.ToDouble(strNumberB), strOperate));
                Console.WriteLine("結果是:" + strResult);
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine("您的輸入有錯:" + ex.Message);
            }
        }
    }

上述代碼實現了業務邏輯與界面的分離,可是尚未真正運用到程序的精髓所在:封裝、繼承、多態,帶着思考和疑問,咱們作出進一步修改以下:

 /// <summary>
    /// 運算類
    /// </summary>
    public class Operaion
    {
        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;
        }
    }
    /// <summary>
    /// 加法類,繼承運算類
    /// </summary>
    class OpertionAdd : Operaion
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA + NumberB;
            return result;
        }
    }
    /// <summary>
    /// 減法類,繼承運算類
    /// </summary>
    class OperationSub : Operaion
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA - NumberB;
            return result;
        }
    }
    /// <summary>
    /// 乘法類,繼承運算類
    /// </summary>
    class OperationMul : Operaion
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA * NumberB;
            return result;
        }
    }

    /// <summary>
    ///除法類,繼承運算類
    /// </summary>
    class OperationDiv : Operaion
    {
        public override double GetResult()
        {
            double result = 0;
            if (NumberB == 0)
                throw new Exception("除數不能爲0.");
            result = NumberA / NumberB;
            return result;
        }
    }

上述代碼寫完,此時就有一個疑問,如何讓計算器知道咱們但願用哪個算法呢?

下面咱們看看簡單運算工廠類

 public class OperationFactory
    {
        public static Operaion createOperate(string operate)
        {
            Operaion oper = null;
            switch (operate)
            { 
                case "+":
                    oper = new OpertionAdd();
                    break;
                case "-":
                    oper = new OperationSub();
                    break;
                case "*":
                    oper = new OperationMul();
                    break;
                case "/":
                    oper = new OperationDiv();
                    break;
            }
            return oper;
        }

    }

有了運算工廠類,咱們只須要輸入運算符號,工廠就能實例化適合的對象,經過多態,返回父類的方法實現了計算器的結果,客戶端代碼以下:

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();
                //調用工廠類進行計算
                Operaion oper;
                oper = OperationFactory.createOperate(strOperate);
                oper.NumberA =double.Parse(strNumberA);
                oper.NumberB =double.Parse(strNumberB);
                //返回計算結果
                var  strResult = oper.GetResult();
                Console.WriteLine("結果是:" + strResult);
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine("您的輸入有錯:" + ex.Message);
            }
        }
    }

這樣,無論咱們是控制檯程序、Windows程序,Web程序或者手機程序,均可以使用這段代碼來實現計算器的功能,若是有一天咱們須要更改加法運算,咱們改OperationAdd就能夠了,若是須要增長其餘複雜運算,好比平方根、立方根,咱們只須要增長相應的運算子類和運算類工廠,再switch中增長分支便可。

UML類圖

相關文章
相關標籤/搜索