工廠方法到抽象工廠模式mysql
設計原則
要依賴抽象,不要依賴具體類
sql
簡單工廠模式雖然簡單,但存在一個很嚴重的問題。當系統中須要引入新產品時,因爲靜態工廠方法經過所傳入參數的不一樣來建立不一樣的產品,這一定要修改工廠類的源代碼,將違背「開閉原則」,如何實現增長新產品而不影響已有代碼?工廠方法模式應運而生,本文將介紹第二種工廠模式——工廠方法模式。數據庫
1 什麼是工廠方法模式ide
工廠方法模式(Factory Method Pattern)又稱爲工廠模式,也叫虛擬構造器(Virtual Constructor)模式或者多態工廠(Polymorphic Factory)模式,它屬於類建立型模式。sqlserver
在工廠方法模式中,工廠父類負責定義建立產品對象的公共接口,而工廠子類則負責生成具體的產品對象,這樣作的目的是將產品類的實例化操做延遲到工廠子類中完成,即經過工廠子類來肯定究竟應該實例化哪個具體產品類。測試
2 爲何要用該模式this
在簡單工廠模式中只提供一個工廠類,該工廠類處於對產品類進行實例化的中心位置,它須要知道每個產品對象的建立細節,並決定什麼時候實例化哪個產品類。簡單工廠模式最大的缺點是當有新產品要加入到系統中時,必須修改工廠類,須要在其中加入必要的業務邏輯,這違背了「開閉原則」。.net
此外,在簡單工廠模式中,全部的產品都由同一個工廠建立,工廠類職責較重,業務邏輯較爲複雜,具體產品與工廠類之間的耦合度高,嚴重影響了系統的靈活性和擴展性,而工廠方法模式則能夠很好地解決這一問題。設計
在工廠方法模式中,再也不提供一個統一的工廠類來建立全部的產品對象,而是針對不一樣的產品提供不一樣的工廠,系統提供一個與產品等級結構對應的工廠等級結構。code
3 模式的結構
7017386-4a72e4cf30c1f0c6.png
在工廠方法模式結構圖中包含以下幾個角色:
- Factory(抽象工廠類|接口):在抽象工廠類中,聲明瞭工廠方法(Factory Method),用於返回一個產品。抽象工廠是工廠方法模式的核心,全部建立對象的工廠類都必須實現該接口。
- ConcreteFactory(具體工廠類):它是抽象工廠類的子類,實現了抽象工廠中定義的工廠方法,並可由客戶端調用,返回一個具體產品類的實例。
- Product(抽象產品類):它是定義產品的接口,是工廠方法模式所建立對象的超類型,也就是產品對象的公共父類。
- (ConcreteProduct具體產品類):它實現了抽象產品接口,某種類型的具體產品由專門的具體工廠建立,具體工廠和具體產品之間一一對應。
與簡單工廠模式相比,工廠方法模式最重要的區別是引入了抽象工廠角色,抽象工廠能夠是接口,也能夠是抽象類或者具體類。
視頻課:https://edu.csdn.net/course/detail/30808
4 代碼示例
代碼參考圖:
抽象工廠能夠建立mysql的操做,也能夠建立sqlserver的操做。
定義一個方法,返回IUserDao接口便可,這樣實現交由子類工廠來實現。
4.1 User實體類
//實體類:和數據庫表一致; public class User { //構造方法 public User(int id,string name) { this.id = id; this.name = name; } int id; public int Id { get { return id; } set { id = value; } } string name; public string Name { get { return name; } set { name = value; } } //重寫該類的ToString(){} public string ToString() { return "編號:"+Id+",姓名:"+Name; } }
4.2 IUserDao接口
//這個接口是定義對User類的操做 public interface IUserDao { void addUser(User user); }
4.3 MysqlUserDao實現類
public class MysqlUserDao:IUserDao { public void addUser(User user) { Console.WriteLine(user.ToString()); Console.WriteLine("mysql開始對user表進行操做了"); } }
4.4 SqlserverUserDao實現類
public class SqlserverUserDao:IUserDao { public void addUser(User user) { Console.WriteLine(user.ToString()); Console.WriteLine("sql server開始對user表進行操做了"); } }
4.5 IFactory接口
public interface IFactory { //返回的是IUserDao的接口; IUserDao createUserDao(); //也能夠建立其餘表操做的接口, //這時候是否是工廠與數據庫無關; }
4.6 MysqlFactory實現類
public class MysqlFactory:IFactory { //返回一個接口的對象;接口不能被new,能夠new它的實現類; public IUserDao createUserDao() { return new MysqlUserDao(); } }
4.7 SqlserverFactory實現類
public class SqlserverFactory:IFactory { public IUserDao createUserDao() { return new SqlserverUserDao(); } }
4.8 測試類
class Program { //程序的健壯性更強,擴展性更好!!!支持多數據庫源; static void Main(string[] args) { User user = new User(1,"張三"); //聲明工廠對象; //IFactory factory = new SqlserverFactory(); IFactory factory = new MysqlFactory(); //讓sqlserver工廠對象幹活 IUserDao iu=factory.createUserDao(); //執行增長用戶的操做; iu.addUser(user); Console.Read(); } }
設計完畢以後,開始寫測試類
5 優勢和缺點
5.1 優勢
- 在工廠方法模式中,工廠方法用來建立客戶端所須要的產品,同時還向客戶端隱藏了哪一種具體產品類將被實例化這一細節,客戶端只須要關心所需產品對應的工廠,無須關心建立細節,甚至無須知道具體產品類的類名。
- 基於工廠角色和產品角色的多態性設計是工廠方法模式的關鍵。它可以使工廠能夠自主肯定建立何種產品對象,而如何建立這個對象的細節則徹底封裝在具體工廠內部。工廠方法模式之因此又被稱爲多態工廠模式,是由於全部的具體工廠類都具備同一抽象父類。
- 使用工廠方法模式的另外一個優勢是在系統中加入新產品時,無須修改抽象工廠和抽象產品提供的接口,無須修改客戶端,也無須修改其餘的具體工廠和具體產品,而只要添加一個具體工廠和具體產品就能夠了。這樣,系統的可擴展性也就變得很是好,徹底符合「開閉原則」。
5.2 缺點
- 在添加新產品時,須要編寫新的具體產品類,並且還要提供與之對應的具體工廠類,系統中類的個數將成對增長,在必定程度上增長了系統的複雜度,有更多的類須要編譯和運行,會給系統帶來一些額外的開銷。
- 因爲考慮到系統的可擴展性,須要引入抽象層,在客戶端代碼中均使用抽象層進行定義,增長了系統的抽象性和理解難度,且在實現時可能須要用到DOM、反射等技術,增長了系統的實現難度。
工廠方法模式比起簡單工廠模式更加符合開閉原則。
工廠模式須要額外建立諸多 Factory 類,也會增長代碼的複雜性,並且,每一個 Factory 類只是作簡單的 new 操做,功能很是單薄(只有一行代碼),也不必設計成獨立的類,因此,在這個應用場景下,簡單工廠模式簡單好用,比工廠方法模式更加合適。
6 適用環境
- 一個類不知道它所須要的對象的類:在工廠方法模式中,客戶端不須要知道具體產品類的類名,只須要知道所對應的工廠便可,具體的產品對象由具體工廠類建立;客戶端須要知道建立具體產品的工廠類。
- 一個類經過其子類來指定建立哪一個對象:在工廠方法模式中,對於抽象工廠類只須要提供一個建立產品的接口,而由其子類來肯定具體要建立的對象,利用面向對象的多態性和里氏代換原則,在程序運行時,子類對象將覆蓋父類對象,從而使得系統更容易擴展。
- 將建立對象的任務委託給多個工廠子類中的某一個,客戶端在使用時能夠無須關心是哪個工廠子類建立產品子類,須要時再動態指定,可將具體工廠類的類名存儲在配置文件或數據庫中。