在簡單工廠的講解中,出現了很多問題,我們對象統一行為抽象出一個接口(或者抽象類)之后,再根據你傳入的類型進行創建實例,這只適合於你有固定行為的場合,當你要實現接口的類型處於不定數時,則不適合使用簡單工廠模式,而應該用工廠方法了。
適用場合:
子類有統一的操作行為
子類的數量不固定,隨時可能有新的功能子類出現
工廠方法優勢:
子類與子類是並列的,關系不精密,程序耦合度比較大
完全符合OCP原則,對代碼的修改關閉,對代碼的擴展開放
創建具體對象方法靈活,可以使用反射或者第三方IOC容器
工廠方法模式代碼片斷,主要從簡單工廠中修改過來的,下面是結果圖
1 統一操作行為,主要將統一接口抽象出來,讓具體子類去實現它
1 /// <summary> 2 /// 工廠方法的規定操作行為 3 /// </summary> 4 public interface ICreate 5 { 6 void Create(); 7 }
如果它的一部分功能對於子類是公用的,相同的,那我們需要將ICreate設計成抽象類abstract class ,代碼可以是這樣
1 public abstract class CreateBase 2 { 3 /// <summary> 4 /// 每個子類都公用的屬性或者方法 5 /// </summary> 6 protected string CreateName 7 { 8 get 9 { 10 return "一個工廠方法模式"; 11 } 12 } 13 /// <summary> 14 /// 子類必須去實現的抽象方法行為 15 /// </summary> 16 abstract void Create(); 17 }
而一個建立抽象行為的工廠,它可以被其它具體行為工廠繼承,它提供一個方法,叫子類工廠去實現它,並返回子類對象本身。同樣,根據業務需求,可以由抽象類實現
1 /// <summary> 2 /// 抽象工廠規定行為 3 /// </summary> 4 public interface CreateFactory 5 { 6 ICreate CreateObject(); 7 }
對於具體對象而言,它們要做的就是去實現抽象的行為,以下是一個人物類,它去實現Create方法。
1 /// <summary> 2 /// 具體對象實現 3 /// </summary> 4 public class People : ICreate 5 { 6 7 #region ICreate 成員 8 9 public void Create() 10 { 11 Console.WriteLine("創建人類"); 12 } 13 14 #endregion 15 }
而對於具體工廠來說,主要作用是去創建一個具體對象的實例,代碼如下:
1 /// <summary> 2 /// 具體工廠進行生產對象 3 /// </summary> 4 public class PeopleFactory : CreateFactory 5 { 6 #region CreateFactory 成員 7 8 public ICreate CreateObject() 9 { 10 return new People(); 11 } 12 13 #endregion 14 }
以程序調用時,我們需要先去創建一個工廠,然后再使用工廠中的方法,來完成我們的操作
1 FactoryMethod.CreateFactory createFactory = new FactoryMethod.PeopleFactory(); 2 FactoryMethod.ICreate iCreate = createFactory.CreateObject(); 3 iCreate.Create();
而這時,我們看到,代碼有些不完美,那就是在創建具體工廠時還是出現了new,即還是存在着代碼間的依賴,如何解除這樣依賴使代碼更加松耦合呢,這時,我們可以使用反射或者IOC
容器來解決這個問題:
1 string strfactoryName = ConfigurationManager.AppSettings["factoryName"]; 2 FactoryMethod.CreateFactory factory = (FactoryMethod.CreateFactory)Assembly.Load("FactoryMethod").CreateInstance("FactoryMethod." + strfactoryName); 3 FactoryMethod.ICreate create = factory.CreateObject(); 4 create.Create();
我們從代碼中可以看到,具體工廠的創建已經被約束到了配置文件中,這是我們可以接受的,呵呵。
事實上,微軟自己在它的組件中大大使用了工廠方法模式,如MVC中的Controller的創建方法,也是這個道理。