簡單工廠模式,用一句話概括其特性:使用子類繼承並重寫父類的方法,在實例化時,通過用戶輸入的參數,使用父類的實例化子類方法,返回相對應的子類,並訪問該子類的屬性及方法;
打個比方,我們去超市買可樂,有的人喜歡百事可樂,有的人喜歡可口可樂,那我們買可樂的過程用代碼表示出來是什麼樣的?看看下面的代碼:
/// <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 修飾符用於方法;