簡單工廠模式

          簡單工廠模式,用一句話概括其特性:使用子類繼承並重寫父類的方法,在實例化時,通過用戶輸入的參數,使用父類的實例化子類方法,返回相對應的子類,並訪問該子類的屬性及方法;

         打個比方,我們去超市買可樂,有的人喜歡百事可樂,有的人喜歡可口可樂,那我們買可樂的過程用代碼表示出來是什麼樣的?看看下面的代碼:

    /// <summary>
    /// 可口可樂
    /// </summary>
    public class KeKou
    {
        public string KeLe()
        {
            return "I'm KeKouKeLe";
        }
    }

    /// <summary>
    /// 可口可樂
    /// </summary>
    public class BaiShi
    {
        public string KeLe()
        {
            return "I'm BaiShiKeLe";
        }
}

那麼我們在超市裏面買可樂的過程用代碼表示出來應該是什麼樣的?我想應該是這樣的:

            //購買百事可樂的過程
            BaiShi baiShi = new BaiShi();
            string keLe = baiShi.KeLe();

            //購買可口可樂的過程
            KeKou keKou = new KeKou();
            string keLe = keKou.KeLe();

通過上面的代碼,我們分別拿到了百事可樂和可口可樂;

忽然有一天我們出差了,要買可樂,但是在外面找不到超市,只有自動售販機,這下習慣在超市買東西的同志們犯難了,以前可以直接把東西拿出來,現在不行了,只能通過售販機幫你取出來,經過研究,發現自動售販機的使用流程是這樣的:先把錢投到售販機裏面,如果我們要百事可樂,就按1號鍵,如果我們要可口可樂,就按2號鍵,這個流程怎麼表示出來呢?我想應該是下面這樣的:


 我們告訴售販機需要什麼樣的可樂,售販機將我們需要的可樂吐出來;我想實現的代碼應該是下面的樣子:

    /// <summary>
    /// 可樂
    /// </summary>
    public class Cola
    {
        public virtual string KeLe()
        {
            return "I'm KeLe";
        }

        public Cola GetKeLe(int index)
        {
            switch (index)
            { 
                case 1:
                    return new BaiShi();
                default :
                    return new KeKou();
            }
        }
}

    下面的百事和可口繼承可樂,代碼如下:

    /// <summary>
    /// 可口可樂
    /// </summary>
    public class KeKou:Cola
    {
        public override string KeLe()
        {
            return "I'm KeKouKeLe";
        }
    }

    /// <summary>
    /// 百事可樂
    /// </summary>
    public class BaiShi:Cola
    {
        public override string KeLe()
        {
            return "I'm BaiShiKeLe";
        }
}

那麼客戶端的代碼應該爲:

Cola cola = new Cola();

       cola = cola.GetKeLe(1);

    cola.KeLe();

上面的代碼是不是很彆扭?首先實例化了一個Cola類,然後將該實例的指向轉爲cola.GetKeLe(1),這裏是簡單工廠需要注意的地方之一:Cola cola = new Cola()代碼實例化了一個Cola對象,該對象擁有的是Cole的屬性和方法,與子類沒有任何關係,所以此時通過cola訪問不到任何與子類相關的內容;cola = cola.GetKeLe(1)代碼實際上做了兩件事情,首先是根據用戶輸入的參數實例化子類,然後將cola實例的指向轉到剛纔生成的子類上,所以此時即可通過cola訪問子類的相關內容;

上面說到了這麼寫難看,那麼我們怎麼改一下?代碼如下:

    /// <summary>
    /// 可樂工廠
    /// </summary>
    public class Cola
    {
        public virtual string KeLe()
        {
            return "I'm KeLe";
        }

        public static Cola GetKeLe(int index)
        {
            switch (index)
            {
                case 1:
                    return new BaiShi();
                default:
                    return new KeKou();
            }
        }
}

上面的代碼只是在工廠類的創建對象方法上添加了一個關鍵字:static,使這個方法變爲靜態方法,同時改變了該方法的訪問模式:通過類可以直接訪問該方法,而不需要通過類的實例訪問;修改後我們再看看客戶端上應該怎樣訪問:

            Colacola = Cola.GetKeLe(1);

        cola.KeLe();

上面的代碼不僅更符合邏輯,也更貼近真實的情況;

另外在簡單工廠方法中還有一點需要注意,父類的方法必須提供爲虛方法,繼承父類的子類對父類虛方法進行重寫,我們來看看下面的代碼:

父類:

    /// <summary>
    /// 可樂工廠
    /// </summary>
    public class Cola
    {
        public virtual string KeLe()
        {
            return "I'm KeLe";
        }

        public static Cola GetKeLe(int index)
        {
            switch (index)
            {
                case 1:
                    return new BaiShi();
                default:
                    return new KeKou();
            }
        }
}

子類:

    /// <summary>
    /// 可口可樂
    /// </summary>
    public class KeKou : Cola
    {
        public new string KeLe()
        {
            return "I'm KeKouKeLe";
        }
    }

    /// <summary>
    /// 可口可樂
    /// </summary>
    public class BaiShi : Cola
    {
        public new string KeLe()
        {
            return "I'm BaiShiKeLe";
        }
}

此時通過客戶端代碼訪問:

            Colacola = Cola.GetKeLe(1);

        cola.KeLe();

得到的解決是我們訪問了父類中的方法,這裏需要弄清楚兩個關鍵字的用途:new和override;

Msdn上這麼解釋的,new:用於向基類成員隱藏繼承成員;override:修飾符用於重寫基類中方法的方法,當基類不包含具有相同簽名的成員時,不得將 override 修飾符用於方法;


發佈了41 篇原創文章 · 獲贊 7 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章