設計模式 _第二招式_工廠方法模式
阿新 • • 發佈:2018-11-07
一、定義
工廠方法模式使用的頻率非常高,在我們日常的開發中總能看到它的身影。其定義為:定義一個用於建立物件的介面,讓子類決定例項化哪一個類。工程方法使用一個類的例項化延遲到其子類。
二、程式碼演示
在工廠方法模式中, 抽象產品類Product負責定義產品的共性,實現對事物最抽象的定義;Creater為抽象建立類,已經是抽象工程,具體如何建立產品類是由具體的實現工程ConcreteCreator完成的。工程方法的變種比較多,下面是一個比較通用的原始碼。
工廠方法模式通用的類圖,如下:
- 抽象產品類
public abstract class Product {
//產品類的公共方法
public void method1(){
//業務邏輯
}
//抽象方法
public abstract void method2();
}
- 具體產品類
具體的產品可以有多個,都繼承於抽象產品類,其原始碼如下:
public class ConcreteProduct1 extends Product {
public void method2(){
//業務邏輯處理
}
}
public class ConcreteProduct2 extends Product {
public void method2(){
//業務邏輯處理
}
}
- 抽象工廠
抽象工程負責定義產品物件的產生,原始碼如下:
public abstract class Creator {
public abstract <T extends Product > T createProduct(Class<T> c);
}
- 具體工廠類
具體如何產生一個產品的物件,是由具體工廠實現的,程式碼如下:
public class ConcreteCreator extends Creator {
public <T extends Product> T createProduct(Class<T> c){
Product product = null ;
try {
product =(Product)Class.forName(c.getName()).newInstance();
}catch (Exception e){
}
return (T)product;
}
}
- 場景類
場景負責呼叫方法,程式碼如下:
public class Client {
public static void main(String args[]){
Creator creator = new ConcreteCreator();
Product product = creator.createProduct(ConcreteProduct1.class);
/**
* 繼續業務處理
*/
}
}
三、優點
- 良好的封裝性,程式碼結構清晰。一個物件建立有條件約束的,如一個呼叫者需要是一個具體的產品物件,只要知道這個產品的類名(或約束字串)就可以了。
不需要知道過程,降低模組間的耦合。 - 工廠方法模式的擴充套件性非常優秀。在增加產品的情況下,只要適當修改具體的工程類或擴充套件一個工程類,就可以“擁抱變化”。
- 遮蔽產品類。這一特點非常重要,產品類的實現如何變化,呼叫者都不需要關係,只需要關心產品的介面,只要介面保持不變,系統中的上層模組就不要發生變化。在資料庫開發中,應該能體會到工廠方法模式的好處,我們要將mysql
資料庫, 切換到oracle 資料庫,只需要修改一下驅動名稱,這就是工廠方法模式的案例。 - 工廠方法模式是典型的解耦框架。高層模組值需要知道產品的抽象類,其他的實現類都不用關心,符合迪米特法則,我不需要的就不要去交流;也符合依賴倒置原則,值依賴產品類的抽象;也符合里氏替換原則,使用產品子類替換為父類。
四、缺點
需要謹慎考慮是否需要增加一個工廠類管理,增加程式碼的複雜度。
五、應用場景
- 工廠方法模式是new一個物件的替代品,所以在所有需要生成物件的地方都可以使用,但是需要謹慎考慮是否需要增加一個工廠類管理,增加程式碼的複雜度。
- 需要靈活的、可擴充套件的框架時,可以考慮工廠方法模版。萬物皆物件,那萬物就是產品類,例如需要設計一個連線郵件伺服器的框架,有三種網路協議可選擇:POP3、IMAP、HTTP,我們就把這三種連線方法作為產品類,定義一個藉口如IConnectMail,然後定義郵件操作的方法,用不同的方法實現三個具體的產品類,在定義一個工廠方法,按照不同的傳入條件,選擇不同的連線方式。如此設計可做到完美擴充套件,如某些伺服器提供webservice介面,很好,我們只要增加一個產品類就可以了。
- 工廠方法模版可以用在異構專案中,例如通過webservice與一個非java的專案互動,雖然webservice號稱是可以做到異構系統的同構化,但是實際開發中還是會碰到很多問題,如型別問題、WSDL檔案的支援問題,等等。從WSDL中產生的物件都認為是一個產品,然後有一個具體的工程進行管理,減少與外圍的耦合。
- 可以使用測試驅動開發的框架下。例如,測試一個類A,就需要把與類A有關聯關係的類B也同步生產出來,我們可以用工廠方法模版把類B虛擬出來,避免類A與類B的耦合。目前由於JMock和EasyMock的誕生,該使用場景已經弱化,讀者可以在遇到此情況時候直接考慮使用JMock和EasyMock。
六、注意事項