工廠方法模式(Factory Method),定義了一個用於建立對象的接口,讓子類決定實例化哪個類。工廠方法使一個類的實例化延遲到子類。javascript
工廠方法模式在實現時,客戶端須要決定實例化哪個工廠來實現運算類,選擇判斷的問題還存在,也就是說,工廠方法把簡單工廠的內部邏輯判斷移到了客戶端代碼來進行。想要加功能,原本是修改工廠類的,而如今是修改客戶端。html
下面給出工廠方法模式UML圖:java
工廠方法模式示例:git
namespace 工廠方法模式 { //數據庫類 class DataBase { public virtual string SelectTopOne() { return "SELECT TOP 1 * FROM Table"; } } //SQLServer類 class SQLServer : DataBase { public override string SelectTopOne() { return "SELECT TOP 1 * FROM Table"; } } //Oracle類 class Oracle : DataBase { public override string SelectTopOne() { return "SELECT * FROM Table WHERE ROWRUM <= 1"; } } //總結來講,下面的1個接口兩個類實現的就是簡單工廠中switch的功能 //數據庫工廠 interface IFactory { DataBase GetDataBase(); } //SQLServer工廠 class SQLServerFactory : IFactory { public DataBase GetDataBase() { return new SQLServer(); } } //Oracle工廠 class OracleFactory : IFactory { public DataBase GetDataBase() { return new Oracle(); } } class Program { static void Main(string[] args) { IFactory factory = new SQLServerFactory(); //依賴於具體工廠類,但不依賴具體實現了了 DataBase DB = factory.GetDataBase(); //從得到的工廠中 獲取學雷鋒對象 Console.WriteLine(DB.SelectTopOne()); //可是我有一種很強烈的感受,既然如此,何不這樣,雖然依賴了具體實現類,可是少了3個類 //DataBase DB = new SQLServer(); //Console.WriteLine(DB.SelectTopOne()); Console.ReadKey(); } } }
類圖以下:數據庫
爲了對比與簡單工廠模式的區別,如下再寫個簡單工廠模式的來比較下:設計模式
namespace 簡單工廠 { public class Program { static void Main(string[] args) { DataBase DB = SimpleFactory.GetInstance("Oracle"); Console.WriteLine(DB.SelectTopOne()); DataBase DB2 = SimpleFactory.GetInstance("SQLServer"); Console.WriteLine(DB2.SelectTopOne()); Console.ReadKey(); } } //簡單工廠類,判斷類,用於返回對應的的對象 public class SimpleFactory { public static DataBase GetInstance(string type) { DataBase db = null; switch (type) { default: case "SQLServer": db = new SQLServer(); break; case "Oracle": db = new Oracle(); break; } return db; } } //基類 public class DataBase { public virtual string SelectTopOne() { return "SELECT TOP 1 * FROM Table"; } } //實現類1 public class SQLServer : DataBase { public override string SelectTopOne() { return "SELECT TOP 1 * FROM Table"; } } //實現類2 public class Oracle : DataBase { public override string SelectTopOne() { return "SELECT * FROM Table WHERE ROWRUM <= 1"; } } }
比較一下,二者實現的代碼相似。ide
對於簡單工廠模式,在客戶端方面,去除了對具體雷鋒的依賴,便可以不出現具體的雷鋒類(如大學生,社區志願者)。但若是要添加一個學雷鋒的中學生,就須要修改工廠類裏面的case判斷,以及添加一個具體類。post
對於工廠方法模式,由客戶端方面來決定實例化哪個工廠來實現運算類,固然判斷的問題仍是存在。相比於簡單工廠,判斷的工做交到客戶端來處理。可是有一個好處,就是當須要添加一個DB2實現時,就沒有必要再修改原有的工廠類,只須要添加一個工廠類(這就是爲什麼這麼多工廠類,一個實現類就有一個工廠類),以及具體類(如例子中的SQLServer、Oracle)。this
客戶端new的地方。相對於簡單工廠而言,對修改封閉了,符合開放封閉原則。可是帶來了代價就是類比較多(工廠類太多了,找死你)。spa