工廠方法模式


  一、 工廠方法(Factory Method)模式

  工廠方法模式(Factory Method),定義一個用於創建對象的接口,讓子類決定實例化那一個類。工廠方法使一個類的實例化延遲至其子類。因為簡單工廠模式一定程度上會違背開方-封閉的原則,但工廠方法由於使用了多態性,工廠方法模式保持了簡單工廠模式的優點,而且克服了它的缺點,工廠方法模式是簡單工廠模式的進一步抽象與推廣,還有工廠方法更復雜的層次結構,可以應用於產品結果復雜的場合。

  在工廠方法模式中,核心的工廠類不再負責產品的創建,而是把具體的創建工作交給子類去完成。核心的工廠類只負責給出具體工廠必須實現的接口,而不會去接觸,實例化任何一個產品。這使得工廠訪求模式可以允許系統在不修改工廠角色的情況下引進新產品。

  二、 工廠方法模式的角色與結構:

  抽象工廠(Creator)角色:是工廠方法模式的核心,與應用程序無關。任何在模式中創建的對象的工廠類必須實現這個接口。

  具體工廠(Concrete Creator)角色:這是實現抽象工廠接口的具體工廠類,包含與應用程序密切相關的邏輯,並且受到應用程序調用以創建產品對象。

  抽象產品(Product)角色:工廠方法模式所創建的對象的超類型,也就是產品對象的共同父類或共同擁有的接口。在上圖中,這個角色是Light。

  具體產品(Concrete Product)角色:這個角色實現了抽象產品角色所定義的接口。某具體產品有專門的具體工廠創建,它們之間往往一一對應。

      結構圖:

    

              

  三、簡單工廠與工廠方法的區別
  簡單工廠最大的優點在於簡單工廠包含必要的邏輯判斷,根據客戶端的條件動態的實例化相關的類,對於客戶端來說,去除了具體產品的依賴。
  工程方法模式(Factory Mode)定義一個用於創建對象的接口,讓子類決定實例化哪一個類,工廠方法使一個類的實例化延長到其子類。

  四、工廠方法的實例

  下面用一個實例來說明一下工廠方法。在簡單工廠模式用過寫windows 計算器的應用(例子源於<<大話設計模式>>)。假如現在需要給計算器添加一個M的N次方的計算方式時,就要在原來的運算工廠類添加M的N次的判斷分支。這違背了"開放-封閉"原則,那么在簡單工廠的基礎上,做進一步的推廣,把它修改成工廠方法模式。

  計算器的UML圖:

        

  運算工廠類不再實例化計算類的對象,而把實例化的工作交給其子類,運算工廠類只負責給出具體運算必須實現的接口。

  部分代碼:

/// <summary>
    /// 運算類
    /// </summary>
    class Operation
    {
        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; }
        }

        /// <summary>
        /// 得到運算結果
        /// </summary>
        /// <returns></returns>
        public virtual double GetResult()
        {
            double result = 0;
            return result;
        }
    }

 

 /// <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>
    interface IFactory
    {
        Operation CreateOperation();
    }
  /// <summary>
    /// 專門負責生產“+”的工廠
    /// </summary>
    class AddFactory : IFactory
    {
        public Operation CreateOperation()
        {
            return new OperationAdd();
        }
    }

    /// <summary>
    /// 專門負責生產“-”的工廠
    /// </summary>
    class SubFactory : IFactory
    {
        public Operation CreateOperation()
        {
            return new OperationSub();
        }
    }

    /// <summary>
    /// 專門負責生產“*”的工廠
    /// </summary>
    class MulFactory : IFactory
    {
        public Operation CreateOperation()
        {
            return new OperationMul();
        }
    }

    /// <summary>
    /// 專門負責生產“/”的工廠
    /// </summary>
    class DivFactory : IFactory
    {
        public Operation CreateOperation()
        {
            return new OperationDiv();
        }
    }
Cilent 調用范例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace 工廠方法模式
{
    class Program
    {
        static void Main(string[] args)
        {
            IFactory operFactory = new AddFactory();
            Operation oper = operFactory.CreateOperation();
            oper.NumberA = 1;
            oper.NumberB = 2;
            double result = oper.GetResult();

            Console.WriteLine(result);

            Console.Read();
        }
    }
}

 

 

  

  

 

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM