工廠模式之簡單工廠

1. 引入

  簡單工廠的本質是,工廠根據傳入的參數,動態的決定應該使用哪個產品(產品是接口的具體實現)。其中涉及三類角色:java

  (1)工廠角色。負責建立全部實例。工廠類中建立產品類的方法能夠被外界直接調用,建立所需的產品對象。web

  (2)抽象產品角色。簡單工廠模式所建立的全部對象的父類,負責描述全部實例共有的公共接口。c#

  (3)具體產品角色。是簡單工廠模式的建立目標,全部建立的對象都是充當這個角色的某個具體類的實例。 設計模式

2. 場景實現

  場景描述:使用c#、java、c、VB任意一種語言實現一個計算器控制檯應用程序,要求輸入兩個數和運算符號,獲得結果。ide

2.1 代碼實現

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("請輸入數字1");
            string num1 = Console.ReadLine();
            Console.WriteLine("請輸入數字2");
            string num2 = Console.ReadLine();
            Console.WriteLine("請輸入運算符號");
            string sysbol = Console.ReadLine();
            string result = "";
            switch (sysbol)
            {
                case "+":result = Convert.ToString(Convert.ToDouble(num1)+Convert.ToDouble(num2)); break;
                case "-":result = Convert.ToString(Convert.ToDouble(num1) - Convert.ToDouble(num2)); break;
                case "*": result = Convert.ToString(Convert.ToDouble(num1) * Convert.ToDouble(num2)); break;
                case "/": result = Convert.ToString(Convert.ToDouble(num1) / Convert.ToDouble(num2)); break;
            }
            Console.WriteLine("result={0}",result);
            Console.OutputEncoding = Encoding.UTF8;
        }
    }

 

2.2 代碼優化

  目前來講,實現加減乘除的功能已經實現,然而程序不易維護擴展,更不易複用。於是,咱們能夠考慮經過封裝、繼承、多態把程序的耦合度下降,用設計模式令程序更加靈活易修改。優化

  假設此時想要寫一個Windows的計算器方法,則目前的代碼就沒法複用,那麼咱們能夠考慮將計算器的實現部分和控制檯的輸出部分進行分離,即讓業務邏輯和界面邏輯分開,減低他們的耦合度達到易維護易擴展。此時,計算器的實現部分就可實現複用。spa

class compute
    {
        public static double getResult(double num1,double num2,string operation)
        {
            double result = 0.0;
            switch (operation)
            {
                case "+": result = num1 + num2; break;
                case "-": result = num1 - num2; break;
                case "*": result = num1 * num2; break;
                case "/":
                    if (num2 != 0)
                        result = num1 / num2;
                    else
                        Console.Write("除數不能爲0");
                break;
            }
            return result;
        }
    }
 static void Main(string[] args)
        {
            Console.WriteLine("請輸入數字1");
            string num1 = Console.ReadLine();
            Console.WriteLine("請輸入數字2");
            string num2 = Console.ReadLine();
            Console.WriteLine("請輸入運算符號");
            string sysbol = Console.ReadLine();
            string result = Convert.ToString(compute.getResult(Convert.ToInt32(num1), Convert.ToInt32(num2), sysbol));
            Console.WriteLine("Hello World!");
        }

2.3 代碼優化2

  上述代碼雖然實現了控制器與具體方法實現的解耦(界面分離),但若是須要增長其餘運算符號時,依然須要編譯已寫好的代碼,此時可能致使修改時會令原有正常運行的代碼在修改時不當心改動發生錯誤。於是,咱們能夠考慮建立一個運算類(父類),令其餘加減乘除的運算類繼承他,從而達到修改或增長較少一個子類不影響其餘類的運行。設計

class Operate
    {
        public int _num1;
        public int _num2;
        public double num1 {
            get { return _num1; }
            set { num1 = _num1; }
        }
        public double num2
        {
            get { return _num2; }
            set { num2 = _num2; }
        }
       
        public virtual double getResult(double n1,double n2)
        {
            double result = 0.0;
            return result;
        }
    }
    class Add:Operate
    {
        
        public override double getResult(double n1, double n2)
        {
            return n1 + n2;
        }
    }
    class Sub : Operate
    {

        public override double getResult(double n1, double n2)
        {
            return n1 - n2;
        }
    }
    class Multiply : Operate
    {
        public override double getResult(double n1, double n2)
        {
            return n1 * n2;
        }
    }
    class  Divide: Operate
    {
        public override double getResult(double n1, double n2)
        {
        if (n2 == 0)

                     throw new Exception("除數不能爲0");
                return n1 / n2;code

      }對象

    }
static void Main(string[] args)
        {
            Console.WriteLine("請輸入數字1");
            string num1 = Console.ReadLine();

            Console.WriteLine("請輸入數字2");
            string num2 = Console.ReadLine();

            Operate sysbol = new Add();
            double result= sysbol.getResult(Convert.ToDouble(num1),Convert.ToDouble(num2));
            Console.WriteLine("{0}", result);
        }

2.3 代碼優化——簡單工廠模式

  上述代碼實現了類的分離,並可以根據對象實例化,可是必須知道須要調用哪一個類,沒法根據輸入的符號進行判斷。所以,如何實現對象實例化,實例化誰,未來要增長的運算怎麼處理,將這些用一個單獨的工廠類實現。完整代碼以下:

class Operate
    {
        public int _num1;
        public int _num2;
        public double num1 {
            get { return _num1; }
            set { num1 = _num1; }
        }
        public double num2
        {
            get { return _num2; }
            set { num2 = _num2; }
        }
       
        public virtual double getResult(double n1,double n2)
        {
            double result = 0.0;
            return result;
        }
    }
    class Add:Operate
    {
        
        public override double getResult(double n1, double n2)
        {
            return n1 + n2;
        }
    }
    class Sub : Operate
    {

        public override double getResult(double n1, double n2)
        {
            return n1 - n2;
        }
    }
    class Multiply : Operate
    {
        public override double getResult(double n1, double n2)
        {
            return n1 * n2;
        }
    }
    class  Divide: Operate
    {
        public override double getResult(double n1, double n2)
        {
            if (n2 == 0)
                throw new Exception("除數不能爲0");
            return n1 / n2;
        }
    }
 class Factory
    {
        /// <summary>
        /// 工廠經過輸入符號實例化對象
        /// </summary>
        /// <param name="operation">運算符號</param>
        /// <returns></returns>
        public static Operate createOperate(string operation)
        {
            Operate oper = null;
            switch (operation)
            {
                case "+": oper = new Add();break;
                case "-":oper = new Sub();break;
                case "*": oper = new Multiply();break;
                case "/":oper = new Divide();break;
            }
            return oper;
        }

    }
class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("請輸入數字1");
            string num1 = Console.ReadLine();
            Console.WriteLine("請輸入數字2");
            string num2 = Console.ReadLine();
            Operate ope = Factory.createOperate("+");
            double result= ope.getResult(Convert.ToDouble(num1), Convert.ToDouble(num2));
            Console.WriteLine("{0}",result);
        }
    }
View Code

  這種實現中,只需輸入運算符號,工廠就能夠實例化出合適的對象,經過多態返回父類的方式實現了計算器的結果。此時,不管是控制檯程序、Windows程序、web程序或其餘手機程序,均可以用上述的工廠方法和運算類。須要增長運算時,只需再增長一個子類繼承Operation,並在工廠方法的switch中添加一個分支便可。封裝、繼承、多態是面向對象的3大特性,也是理解設計模式的基礎。

簡單工廠的UML圖

4. 應用場景

  簡單工廠模式主要適用於抽象子類的業務邏輯相同,但具體實現不一樣的狀況。不一樣的操做子類執行一樣的方法。如以上給出的實現計算器功能,運算的操做都是針對兩個數和一個運算方法,只是運算操做不一樣,就可使用簡單工廠模式。例如,一我的想 開車,家裏有多種類型的車(如跑車、越野車、兩廂車),它們都能實現跑(run)的功能,選擇哪一輛車即對哪一個對象實例化,因爲可能還會增長或減小車,咱們考慮用一個類建立實例。也是簡單工廠的應用。

5. 優劣勢

優勢:

  • 客戶端不須要了解如何建立產品,徹底和產品邏輯解耦,只須要發送指令去「消費」就好,職責明確;
  • 將初始化實例時的工做放到工廠裏進行,使代碼維護更易。更符合面向對象的原則。

缺點:須要增長一個具體對象時,須要在工廠類中增減代碼,違背了面向對象設計的「開放-封閉」原則;

6. 總結

  簡單工廠建立子類實例並傳給外界時只須要知道抽象子類對應的參數便可,而不須要知道抽象子類的建立過程,在外界使用時甚至不用引入抽象子類。簡單工廠明確區分了各個子類的職責和權力,有利於整個軟件體系的優化。

 主要參考:《大話設計模式》

相關文章
相關標籤/搜索