概述
先照搬書上工廠模式的定義,即定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪一個類,工廠方法使一個類的實例化延遲到其子類。工廠模式一共有三個小分類,分別是:簡單工廠模式,工廠方法模式和抽象工廠模式。使用工廠模式一定有他的好處,那么具體好處是啥呢?我認為3個工廠模式有不同的好處,當然他們也不是完美無缺的。下面我們簡單介紹3類工廠模式。
簡單工廠模式
通過一個工廠,產(chǎn)生不同的產(chǎn)品。如下代碼所示。
/**
* 產(chǎn)品接口
*/
public interface Product {
void use();
}
/**
* A產(chǎn)品
*/
public class ProductA implements Product {
public void use() {
System.out.println("use ProductA");
}
}
/**
* B產(chǎn)品
*/
public class ProductB implements Product {
public void use() {
System.out.println("use ProductB");
}
}
/**
* 簡單工廠
*/
public class Factory {
public Product createProduct(String category) {
switch(category) {
case "A":
return new ProductA();
case "B":
return new ProductB();
default:
return null;
}
}
}
通過工廠類,客戶可以根據(jù)不同的參數(shù),就能“拿到”想要的產(chǎn)品,不用自己生產(chǎn)一個。
簡單工廠實際應用舉例
- JDK類庫中廣泛使用了簡單工廠模式
如工具類java.text.DateFormat,它用于格式化一個本地日期或者時間。
public final static DateFormat getDateInstance();
public final static DateFormat getDateInstance(int style);
public final static DateFormat getDateInstance(int style,Locale
locale);
- Java加密技術(shù)
獲取不同加密算法的密鑰生成器:
KeyGenerator keyGen=KeyGenerator.getInstance("DESede");
簡單工廠模式的優(yōu)點
- 將對象的創(chuàng)建和使用分離,客戶不用關心產(chǎn)品的實例化細節(jié),起到了責任分割和降低耦合的作用。
簡單工廠模式的缺點
- 每增加一種產(chǎn)品,就要修改工廠的邏輯,在產(chǎn)品數(shù)量眾多,且類型復雜的情況下,可能難以修改和維護。
- 工廠負責所有產(chǎn)品的創(chuàng)建,責任重大,一旦不能正常工作,整個系統(tǒng)就無法正常工作。
簡單工廠適用場景
產(chǎn)品種類較少時,或者客戶只知道產(chǎn)品種類的參數(shù),并不關心如何產(chǎn)生的情況下,可以使用簡單工廠模式。
工廠方法模式
工廠方法模式不再使用一個工廠完成所有產(chǎn)品的生產(chǎn),而是由特定工廠負責特定產(chǎn)品的生產(chǎn),當我們需要新增某類產(chǎn)品的時候,只需要實現(xiàn)對應產(chǎn)品的生產(chǎn)工廠,然后客戶端調(diào)用對應的工廠生產(chǎn)即可。
/**
* 產(chǎn)品接口
*/
public interface Product {
void use();
}
/**
* 工廠接口
*/
public interface Factory {
Product createProduct();
}
/**
* A產(chǎn)品
*/
public class ProductA implements Product {
public void use() {
System.out.println("use ProductA");
}
}
/**
* B產(chǎn)品
*/
public class ProductB implements Product {
public void use() {
System.out.println("use ProductB");
}
}
/**
* A產(chǎn)品工廠
*/
public class FactoryA implements Factory {
public ProductA createProduct() {
return new ProductA();
}
}
/**
* B產(chǎn)品工廠
*/
public class FactoryB implements Factory{
public Product createProduct() {
return new ProductB();
}
}
工廠方法模式的優(yōu)點
工廠方法模式的缺點
工廠方法模式的實際應用舉例
- 日志記錄器
某系統(tǒng)日志記錄器要求支持多種日志記錄方式,如文件記錄、數(shù)據(jù)庫記錄等,且用戶可以根據(jù)要求動態(tài)選擇日志記錄方式, 現(xiàn)使用工廠方法模式設計該系統(tǒng)。
- JDBC中的工廠方法
Connection conn=DriverManager.getConnection("jdbc:microsoft:sqlserver://loc
alhost:1433; DatabaseName=DB;user=sa;password=");
Statement statement=conn.createStatement();
ResultSet rs=statement.executeQuery("select * from UserInfo");
工廠方法模式的優(yōu)點
- 向客戶隱藏了哪種具體產(chǎn)品類將被實例化這一細節(jié),用戶只需要關心所需產(chǎn)品對應的工廠,無須關心創(chuàng)建細節(jié),甚至無須知道具體產(chǎn)品類的類名。降低了耦合度封裝了變化。
- 增加新產(chǎn)品時,無須修改其他的具體工廠和具體產(chǎn)品,只需要增加具體產(chǎn)品以及具體生產(chǎn)工廠即可。符合“開閉原則”。
工廠方法模式的缺點
- 據(jù)說是:每增加一個產(chǎn)品就需要編寫相關的工廠類,系統(tǒng)類的個數(shù)增加,增加系統(tǒng)復雜度,和編譯速度。(本人不太同意這個觀點。。。)
抽象工廠模式
為了更清晰地理解工廠方法模式,需要先引入兩個概念:
- 產(chǎn)品等級結(jié)構(gòu)
產(chǎn)品等級結(jié)構(gòu)即產(chǎn)品的繼承結(jié)構(gòu),如一個抽象類是電視機,其子類有海爾電視機、海信電視機、TCL電視機,則抽象電視機與具體品牌的電視機之間構(gòu)成了一個產(chǎn)品等級結(jié)構(gòu),抽象電視機是父類,而具體品牌的電視機是其子類。 - 產(chǎn)品族
在抽象工廠模式中,產(chǎn)品族是指由同一個工廠生產(chǎn)的,位于不同產(chǎn)品等級結(jié)構(gòu)中的一組產(chǎn)品,如海爾電器工廠生產(chǎn)的海爾電視機、海爾電冰箱,海爾電視機位于電視機產(chǎn)品等級結(jié)構(gòu)中,海爾電冰箱位于電冰箱產(chǎn)品等級結(jié)構(gòu)中。
在工廠方法模式中,某一個具體工廠負責某一個具體的產(chǎn)品。但是現(xiàn)實中,我們可能需要某一個工廠負責某生產(chǎn)一個產(chǎn)品族的產(chǎn)品。這時使用抽象工廠會比較合適。這里我們使用UML圖來表示抽象抽象工廠模式
抽象工廠的實際使用
- 情景模式的實現(xiàn)
比如黑夜模式下,需要對UI界面的多個元素就行修改,這時可以使用抽象共產(chǎn)模式
抽象工廠的優(yōu)點
- 抽象工廠模式隔離了具體類的生成,使得客戶并不需要知道什么被創(chuàng)建。
- 當一個產(chǎn)品族中的多個對象被設計成一起工作時,它能夠保證客戶端始終只使用同一個產(chǎn)品族中的對象。這對一些需要根據(jù)當前環(huán)境來決定其行為的軟件系統(tǒng)來說,是一種非常實用的設計模式。
- 增加新的具體工廠和產(chǎn)品族很方便(但是增加新的產(chǎn)品等級結(jié)構(gòu)麻煩)
抽象工廠的缺點
在添加新的產(chǎn)品對象時,難以擴展抽象工廠來生產(chǎn)新種類的產(chǎn)品,這是因為在抽象工廠角色中規(guī)定了所有可能被創(chuàng)建的產(chǎn)品集合,要支持新種類的產(chǎn)品就意味著要對該接口進行擴展,而這將涉及到對抽象工廠角色及其所有子類的修改,顯然會帶來較大的不便。
開閉原則的傾斜性(增加新的工廠和產(chǎn)品族容易,增加新的產(chǎn)品等級結(jié)構(gòu)麻煩)。