[設計模式] 簡單工廠(Simple Factory)

  • 8686
  • 0
  • 2010-03-01

[設計模式] 簡單工廠(Simple Factory)

Introduction

(原文出處 大話設計模式 )

大部分的人對於物件導向都有一些了解,利用物件導向的特性(封裝、繼承、多型) 來寫出容易擴充、維護與高重用性的程式,

如同書上介紹的,我想設計模式只是利用物件導向的特性,讓我們去找到「封裝變化」、「物件間鬆散的耦合」、「針對介面程式設計」

的感覺,而達到最終的目的。這是個心得筆記。

 

Example

寫出一個簡單計算機功能的程式,並且這個程式,可以移植到任何的應用程式(ex:Web、PDA、Window)。

先設計一個  Operation 抽象類別作為基底。


 /// <summary>
    /// 運算類別
    /// </summary>
    public abstract 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;
        }
}

 

再來撰寫計算的功能(加法、乘法...),複寫 GetResult() 函式(屬於自己的計算結果)。


 /// <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 OperationDiv : Operation {
        public override double GetResult() {
            double result = 0;
            if (NumberB == 0)
                throw new Exception("除數不能為0。");
            result = NumberA / NumberB;
            return result;
        }
    }

 

撰寫簡單工廠類別,負責實體化要運算的類別(利用多型的技巧)。


/// <summary>
    /// 運算類別工廠
    /// </summary>
    public 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;
                    }
                case "sqr": {
                        oper = new OperationSqr();
                        break;
                    }
                case "sqrt": {
                        oper = new OperationSqrt();
                        break;
                    }
                case "+/-": {
                        oper = new OperationReverse();
                        break;
                    }
            }

            return oper;
        }
    }

 

最後就是 Client 端的程式。


        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 = "";

                Operation oper;
                oper = OperationFactory.createOperate(strOperate);
                oper.NumberA = Convert.ToDouble(strNumberA);
                oper.NumberB = Convert.ToDouble(strNumberB);
                strResult = oper.GetResult().ToString();

                Console.WriteLine("結果是:" + strResult);

                Console.ReadLine();
            }
            catch (Exception ex) {
                Console.WriteLine("您的輸入有錯:" + ex.Message);
            }
        }

 

輸出結果

2010-02-05_013613

 

這個方法切割了介面與演算法,並且依照需求產生相對應的物件,這就是簡單工廠的好處;

若是要擴充運算類別或是修改,也只需針對演算法這一塊,當然,對於判斷建立相對應的運算

物件,還是有缺點,這邊在判斷上就需要花上一些成本,我想很些人會想到 反射 技術。

三小俠  小弟獻醜,歡迎指教