本篇文章介紹一種設計模式——工廠模式。工廠模式是用來封裝對象的創建,減少應用程序和具體類之間的依賴,促進松耦合。根據工廠模式的應用特性,一共分爲三種子模式:簡單工廠模式,工廠方法模式和抽象工廠模式。本篇文章主要介紹簡單工廠模式。本篇文章內容參考《JAVA與模式》之簡單工廠模式。
一、簡單工廠模式簡介
1.定義
簡單工廠模式(Simple Factory Pattern):又稱爲靜態工廠方法(Static Factory Method)模式,它屬於類創建型模式。在簡單工廠模式中,可以根據參數的不同返回不同類的實例。簡單工廠模式專門定義一個類來負責創建其他類的實例,被創建的實例通常都具有共同的父類。
2.使用動機
考慮一個簡單的軟件應用場景:一個軟件系統可以提供多個外觀不同的按鈕(如圓形按鈕、矩形按鈕、菱形按鈕等), 這些按鈕都源自同一個基類,不過在繼承基類後不同的子類修改了部分屬性從而使得它們可以呈現不同的外觀。
如果我們希望在使用這些按鈕時,不需要知道這些具體按鈕類的名字,只需要知道表示該按鈕類的一個參數,並提供一個調用方便的方法,把該參數傳入方法即可返回一個相應的按鈕對象,此時,就可以使用簡單工廠模式。
二、簡單工廠模式結構
1.模式結構
簡單工廠模式包含如下角色:
●Factory:工廠角色
工廠角色負責實現創建所有實例的內部邏輯
●Product:抽象產品角色
抽象產品角色是所創建的所有對象的父類,負責描述所有實例所共有的公共接口
●ConcreteProduct:具體產品角色
具體產品角色是創建目標,所有創建的對象都充當這個角色的某個具體類的實例。
2.時序圖
①先調用工廠類中的靜態方法createProduct()
②根據傳入產品類型參數,獲得具體的產品對象
③返回產品對象並使用
三、簡單工廠的使用實例
以登錄功能來說,假如應用系統需要支持多種登錄方式如:口令認證、域認證(口令認證通常是去數據庫中驗證用戶,而域認證則是需要到微軟的域中驗證用戶)。那麼自然的做法就是建立一個各種登錄方式都適用的接口,如下圖所示:
抽象產品Login
public interface Login {
//登錄驗證
public boolean verify(String name , String password);
}
具體產品DomainLogin
public class DomainLogin implements Login {
@Override
public boolean verify(String name, String password) {
// TODO Auto-generated method stub
/**
* 業務邏輯
*/
return true;
}
}
具體產品PasswordLogin
public class PasswordLogin implements Login {
@Override
public boolean verify(String name, String password) {
// TODO Auto-generated method stub
/**
* 業務邏輯
*/
return true;
}
}
工廠類LoginManager
根據調用者不同的要求,創建出不同的登錄對象並返回。而如果碰到不合法的要求,會返回一個Runtime異常。
public class LoginManager {
public static Login factory(String type){
if(type.equals("password")){
return new PasswordLogin();
}else if(type.equals("passcode")){
return new DomainLogin();
}else{
/**
* 這裏拋出一個自定義異常會更恰當
*/
throw new RuntimeException("沒有找到登錄類型");
}
}
}
測試調用
public class Test {
public static void main(String[] args) {
String loginType = "password";
String name = "name";
String password = "password";
Login login = LoginManager.factory(loginType);
boolean bool = login.verify(name, password);
if (bool) {
/**
* 業務邏輯
*/
} else {
/**
* 業務邏輯
*/
}
}
}
假如不使用簡單工廠模式則驗證登錄Servlet代碼如下:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
String loginType = "password";
String name = "name";
String password = "password";
//處理口令認證
if(loginType.equals("password")){
PasswordLogin passwordLogin = new PasswordLogin();
boolean bool = passwordLogin.verify(name, password);
if (bool) {
/**
* 業務邏輯
*/
} else {
/**
* 業務邏輯
*/
}
}
//處理域認證
else if(loginType.equals("passcode")){
DomainLogin domainLogin = new DomainLogin();
boolean bool = domainLogin.verify(name, password);
if (bool) {
/**
* 業務邏輯
*/
} else {
/**
* 業務邏輯
*/
}
}else{
/**
* 業務邏輯
*/
}
}
}
可以看到非常麻煩,代碼重複很多,而且不利於擴展維護。
四、簡單工廠模式優缺點
優點:
通過使用工廠類,外界不再需要關心如何創造各種具體的產品,只要提供一個產品的名稱作爲參數傳給工廠,就可以直接得到一個想要的產品對象,並且可以按照接口規範來調用產品對象的所有功能(方法)。
構造容易,邏輯簡單。
缺點:
1.簡單工廠模式中的if else判斷非常多,完全是Hard Code,如果有一個新產品要加進來,就要同時添加一個新產品類,並且必須修改工廠類,再加入一個 else if 分支纔可以, 這樣就違背了 “開放-關閉原則”中的對修改關閉的準則了。當系統中的具體產品類不斷增多時候,就要不斷的修改工廠類,對系統的維護和擴展不利。
2.一個工廠類中集合了所有的類的實例創建邏輯,違反了高內聚的責任分配原則,將全部的創建邏輯都集中到了一個工廠類當中,所有的業務邏輯都在這個工廠類中實現。什麼時候它不能工作了,整個系統都會受到影響。因此一般只在很簡單的情況下應用,比如當工廠類負責創建的對象比較少時。
3.簡單工廠模式由於使用了靜態工廠方法,造成工廠角色無法形成基於繼承的等級結構。
適用環境
在以下情況下可以使用簡單工廠模式:
工廠類負責創建的對象比較少:由於創建的對象較少,不會造成工廠方法中的業務邏輯太過複雜。
客戶端只知道傳入工廠類的參數,對於如何創建對象不關心:客戶端既不需要關心創建細節,甚至連類名都不需要記住,只需要知道類型所對應的參數。
五、簡單工廠模式在Java中的應用
①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加密技術
獲取不同加密算法的密鑰生成器:
KeyGenerator keyGen=KeyGenerator.getInstance("DESede");
創建密碼器:
Cipher cp=Cipher.getInstance("DESede");