今天呢,給大家來講一下抽象工廠模式,說到這裡,大家會想到好多種關於工廠的模式,前面已經講了兩種了 簡單工廠模式和工廠方法模式。好,下麵我們來看一下抽象工廠模式。 同樣,我們來舉一個案例 一、案例 我們在做項目的時候,肯定會與資料庫打交道,那麼我們用簡單的控制台應用程式來模擬一個向SqlServer數 ...
今天呢,給大家來講一下抽象工廠模式,說到這裡,大家會想到好多種關於工廠的模式,前面已經講了兩種了 簡單工廠模式和工廠方法模式。好,下麵我們來看一下抽象工廠模式。
同樣,我們來舉一個案例
一、案例
我們在做項目的時候,肯定會與資料庫打交道,那麼我們用簡單的控制台應用程式來模擬一個向SqlServer資料庫表中插入和讀取的情況。
1 /// <summary> 2 /// User中的欄位 3 /// </summary> 4 class User 5 { 6 private int _id; 7 8 public int Id 9 { 10 get 11 { 12 return _id; 13 } 14 15 set 16 { 17 _id = value; 18 } 19 } 20 21 public string Name 22 { 23 get 24 { 25 return _name; 26 } 27 28 set 29 { 30 _name = value; 31 } 32 } 33 34 private string _name; 35 } 36 /// <summary> 37 /// SqlServer類 38 /// </summary> 39 class SqlserverUser 40 { 41 public void Insert(User user) 42 { 43 Console.WriteLine("在Sql server 中 給User 表增加一條記錄"); 44 } 45 46 public User GetUser(int id) 47 { 48 Console.WriteLine($"在Sql server 中根據ID獲取User表中的一條記錄"); 49 return null; 50 } 51 }
客戶端調用:
1 internal class Program 2 { 3 public static void Main() 4 { 5 User user = new User(); 6 SqlserverUser su = new SqlserverUser(); 7 su.Insert(user); 8 su.GetUser(1); 9 Console.ReadKey(); 10 }
二、演繹
1、第一步演繹
那麼問題來了,如果我這個項目資料庫換成Oracle,那麼我豈不是都要改了,如果想實現自由的切換資料庫,我們想到了一個不錯的模式,對,工廠方法模式。
讓他們都依賴於抽象,所以我們在這裡增加兩個介面
1 interface IUser 2 { 3 void Insert(User user); 4 User GetUser(int id); 5 } 6 7 interface IFactory 8 { 9 IUser CraeteUser(); 10 }
讓User 和 SqlServer 等類繼承相應的介面
1 /// <summary> 2 /// SqlServer類 3 /// </summary> 4 class SqlserverUser :IUser 5 { 6 public void Insert(User user) 7 { 8 Console.WriteLine("在Sql server 中 給User 表增加一條記錄"); 9 } 10 11 public User GetUser(int id) 12 { 13 Console.WriteLine($"在Sql server 中根據ID獲取User表中的一條記錄"); 14 return null; 15 } 16 } 17 18 class OracleUser:IUser 19 { 20 public void Insert(User user) 21 { 22 Console.WriteLine("在Oracle 中 給User 表增加一條記錄"); 23 } 24 25 public User GetUser(int id) 26 { 27 Console.WriteLine($"在Oracle 中根據ID獲取User表中的一條記錄"); 28 return null; 29 } 30 }
1 class SqlServerFactory:IFactory 2 { 3 public IUser CraeteUser() 4 { 5 return new SqlserverUser(); 6 } 7 } 8 class OracleFactory : IFactory 9 { 10 public IUser CraeteUser() 11 { 12 return new OracleUser(); 13 } 14 }
客戶端
1 public static void Main() 2 { 3 User user = new User(); 4 IFactory factory = new SqlServerFactory(); 5 IUser su = factory.CraeteUser(); 6 su.Insert(user); 7 su.GetUser(1); 8 Console.ReadKey(); 9 }
以上,我們將案例用工廠方法模式寫出來了。
2、第二步演繹
我們的資料庫中,不可能之後User表,還有很多其他的表,這樣就會產生好多的類哦。
下麵,我們在增加一個表(Department)
那麼,按照上面的模式就會產生一下麵的一坨代碼
1 class Department 2 { 3 private int _id; 4 5 public int Id 6 { 7 get 8 { 9 return _id; 10 } 11 12 set 13 { 14 _id = value; 15 } 16 } 17 18 public string Name 19 { 20 get 21 { 22 return _name; 23 } 24 25 set 26 { 27 _name = value; 28 } 29 } 30 31 private string _name; 32 } 33 interface IDepartment 34 { 35 void Insert(Department department); 36 Department GetDepartment(int id); 37 } 38 39 class SqlServerDepartment:IDepartment 40 { 41 public void Insert(Department department) 42 { 43 Console.WriteLine("在SqlServer 中 給Department 表增加一條記錄"); 44 } 45 46 public Department GetDepartment(int id) 47 { 48 Console.WriteLine("在SqlServer 中 根據ID 獲取Department 表一條記錄"); 49 return null; 50 } 51 } 52 53 class OracleDepartment : IDepartment 54 { 55 public void Insert(Department department) 56 { 57 Console.WriteLine("在Oracle 中 給Department 表增加一條記錄"); 58 } 59 60 public Department GetDepartment(int id) 61 { 62 Console.WriteLine("在Oracle 中 根據ID 獲取Department 表一條記錄"); 63 return null; 64 } 65 }
工廠介面與實現中也新增了方法
1 interface IFactory 2 { 3 IUser CraeteUser(); 4 IDepartment CreateDepartment(); 5 } 6 7 class SqlServerFactory:IFactory 8 { 9 public IUser CraeteUser() 10 { 11 return new SqlserverUser(); 12 } 13 14 public IDepartment CreateDepartment() 15 { 16 return new SqlServerDepartment(); 17 } 18 } 19 class OracleFactory : IFactory 20 { 21 public IUser CraeteUser() 22 { 23 return new OracleUser(); 24 } 25 26 public IDepartment CreateDepartment() 27 { 28 return new OracleDepartment(); 29 } 30 }
經過我們這麼一步一步的演化,我們重構出了一個非常重要的設計模式,抽象工廠模式。小伙伴們會說,剛剛這不是工廠方法模式嗎。
只有一個User表的時候,是只需要工廠方法模式的,但是我們資料庫中顯然有非常多的表,還SqlServer 和Oracle 這兩大分支,所以涉及到解決多種產品分支的問題,有一個專門的工廠模式,叫抽象工廠模式。
什麼叫抽象工廠模式呢?提供一系列相關或相互依賴的介面,而無需指定他們具體的類。
這就是抽象工廠模式,他的優缺點很明顯。
優點:靈活,產品系列零活切換。
缺點:如果我們再增加一個表,需要改動的地方太多了,需要增加三個類,需要修改三個類,靠,太麻煩了吧。
客戶端每一次使用時,需要new 一下,如果客戶端有好多處調用的,那麼就需要new 好多次。 這些都是他的缺點。
編程是一門藝術,這樣大批量的改動,顯然是非常醜陋的做法。
我們這裡有一個改進的方法,就是用簡單工廠方法改進抽象工廠模式。
我們新增加一個類
1 class DataAccess 2 { 3 private static readonly string db = "SqlServer"; 4 // private static readonly string db = "Oracle"; 5 public static IUser CreateUser() 6 { 7 IUser result = null; 8 switch (db) 9 { 10 case "SqlServer": 11 result = new SqlserverUser(); 12 break; 13 case "Oracle": 14 result = new OracleUser(); 15 break; 16 } 17 return result; 18 } 19 20 public static IDepartment CreateDepartment() 21 { 22 IDepartment result = null; 23 switch (db) 24 { 25 case "SqlServer": 26 result = new SqlServerDepartment(); 27 break; 28 case "Oracle": 29 result = new OracleDepartment(); 30 break; 31 } 32 return result; 33 } 34 }
嗯,這樣,客戶端調用的時候就好調用了。
1 public static void Main() 2 { 3 User user = new User(); 4 Department dept = new Department(); 5 IUser iu = DataAccess.CreateUser(); 6 iu.Insert(user); 7 iu.GetUser(1); 8 IDepartment d = DataAccess.CreateDepartment(); 9 d.Insert(dept); 10 d.GetDepartment(1); 11 Console.ReadKey(); 12 }
ok,那麼如果我還想增加一個資料庫類型的分支,比如Access資料庫,那麼需要在DataAccess類的方法中增加一個case 分支。
之前我們也曾提到過相關的問題,就是用 反射 來解決,但一直沒有展開來講,那麼下篇博文,我們來給大家講一講如何用反射的技術來解決這些問題。
反射反射,程式員的快樂~
好了,今天我們先講到這裡,下一篇我們將用反射技術來解決相關的問題~
本系列將持續更新,喜歡的小伙伴可以點一下關註和推薦,謝謝大家的支持。