設計模式 — 工廠模式
簡單工廠模式
-
簡單工廠模式是由一個工廠對象決定創建出哪一種產品類的實例。
-
簡單工廠模式(靜態工廠模式):定義了一個創建對象的類,由這個類來封裝實例化對象的行為(程式碼)
-
在軟體開發中,當我們會用到大量的創建某種、某類或者某批對象時,就會使用到工廠模式.
注意:簡單工廠模式不是23中設計模式之一
-
優點
-
工廠類包含必要的邏輯判斷,可以決定在什麼時候創建哪一個產品的實例。客戶端可以免除直接創建產品對象的職責,很方便的創建出相應的產品。工廠和產品的職責區分明確。
-
客戶端無需知道所創建具體產品的類名,只需知道參數即可。
-
也可以引入配置文件,在不修改客戶端程式碼的情況下更換和添加新的具體產品類。
-
-
缺點
- 簡單工廠模式的工廠類單一,負責所有產品的創建,職責過重,一旦異常,整個系統將受影響。且工廠類程式碼會非常臃腫,違背高聚合原則。
- 使用簡單工廠模式會增加系統中類的個數(引入新的工廠類),增加系統的複雜度和理解難度
- 系統擴展困難,一旦增加新產品不得不修改工廠邏輯,在產品類型較多時,可能造成邏輯過於複雜
- 簡單工廠模式使用了 static 工廠方法,造成工廠角色無法形成基於繼承的等級結構。
應用場景
-
對於產品種類相對較少的情況
-
只知道傳入工廠類的參數,不關心如何創建對象的邏輯
案例
public interface Car {
void name();
}
// 產品1
public class Tesla implements Car {
@Override
public void name() {
System.out.println("特斯拉");
}
}
// 產品1
public class WuLing implements Car {
@Override
public void name() {
System.out.println("五菱");
}
}
// 當我們再添加一個產品,要修改CarFactory中的程式碼,違反了開閉原則
public class CarFactory {
public static Car getCar(String car){
if (car.equals("五菱")){
return new WuLing();
} else if (car.equals("特斯拉")){
return new Tesla();
} else {
return null;
}
}
}
public class Consumer {
public static void main(String[] args){
// 使用new創建對象
// Car car1 = new Tesla();
// Car car2 = new WuLing();
// 通過簡單工廠模式創建
Car car1 = CarFactory.getCar("五菱");
Car car2 = CarFactory.getCar("特斯拉");
car1.name();
car2.name();
}
}
工廠方法模式
用來生產同一等級結構中的固定產品(支援增加任意產品)
案例
public interface Car {
void name();
}
// 工廠方法
public interface CarFactory {
Car getCar();
}
public class BaoMa implements Car {
@Override
public void name() {
System.out.println("寶馬");
}
}
public class BaoMaFactory implements CarFactory {
@Override
public Car getCar() {
return new BaoMa();
}
}
public class Tesla implements Car {
@Override
public void name() {
System.out.println("特斯拉");
}
}
public class TeslaFactory implements CarFactory {
@Override
public Car getCar() {
return new Tesla();
}
}
public class WuLing implements Car {
@Override
public void name() {
System.out.println("五菱");
}
}
public class WuLingFactory implements CarFactory{
@Override
public Car getCar() {
return new WuLing();
}
}
public class Consumer {
public static void main(String[] args){
// 通過工廠方法模式創建
Car car1 = new WuLingFactory().getCar();
Car car2 = new TeslaFactory().getCar();
// 添加新的產品,不需要修改之前的程式碼
Car car3 = new BaoMaFactory().getCar();
car1.name();
car2.name();
car3.name();
}
}
抽象工廠模式
抽象工廠模式提供了一個創建一系列相關或者相互依賴對象的介面,無需指定它們具體的類
適用場景
-
客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節
-
強調一系列相關的產品對象(屬於同一產品族)一起使用創建對象需要大量的重複程式碼
-
提供一個產品類的庫,所有的產品以同樣的介面出現,從而使得客戶端不依賴於具體的實現
優點
- 具體產品在應用層的程式碼隔離,無需關心創建的細節
- 將一個系列的產品統一到一起創建
缺點
- 規定了所有可能被創建的產品集合,產品簇中擴展新的產品困難
- 增加了系統的抽象性和理解難度
案例
public interface IPhoneProduct {
void start();
void shutdown();
void callUp();
void sendEmail();
}
public interface IRouterProduct {
void start();
void shutdown();
void setWife();
void setting();
}
// 抽象產品工廠
public interface ProductFactory {
// 生產手機
IPhoneProduct iphoneProduct();
// 生產路由器
IRouterProduct iRouterProduct();
}
public class XiaomiPhone implements IPhoneProduct {
@Override
public void start() {
System.out.println("小米手機 開機");
}
@Override
public void shutdown() {
System.out.println("小米手機 關機");
}
@Override
public void callUp() {
System.out.println("小米手機 打電話");
}
@Override
public void sendEmail() {
System.out.println("小米手機 發簡訊");
}
}
public class HuaweiiPhone implements IPhoneProduct {
@Override
public void start() {
System.out.println("華為手機 開機");
}
@Override
public void shutdown() {
System.out.println("華為手機 關機");
}
@Override
public void callUp() {
System.out.println("華為手機 打電話");
}
@Override
public void sendEmail() {
System.out.println("華為手機 發簡訊");
}
}
public class XiaomiRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("小米路由器 開啟");
}
@Override
public void shutdown() {
System.out.println("小米路由器 關閉");
}
@Override
public void setWife() {
System.out.println("小米路由器 設置wife");
}
@Override
public void setting() {
System.out.println("小米路由器 相關設置");
}
}
public class HuaweiRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("華為路由器 開啟");
}
@Override
public void shutdown() {
System.out.println("華為路由器 關閉");
}
@Override
public void setWife() {
System.out.println("華為路由器 設置wife");
}
@Override
public void setting() {
System.out.println("華為路由器 相關設置");
}
}
public class XiaomiProductFactory implements ProductFactory {
@Override
public IPhoneProduct iphoneProduct() {
return new XiaomiPhone();
}
@Override
public IRouterProduct iRouterProduct() {
return new XiaomiRouter();
}
}
public class HuaweiProductFactory implements ProductFactory {
@Override
public IPhoneProduct iphoneProduct() {
return new HuaweiiPhone();
}
@Override
public IRouterProduct iRouterProduct() {
return new HuaweiRouter();
}
}
// 測試
public class Client {
public static void main(String[] args){
System.out.println("===== 小米系列產品 =====");
XiaomiProductFactory xiaomiProductFactory = new XiaomiProductFactory();
IPhoneProduct iPhoneProduct = xiaomiProductFactory.iphoneProduct();
iPhoneProduct.start();
iPhoneProduct.callUp();
iPhoneProduct.sendEmail();
IRouterProduct routerProduct = xiaomiProductFactory.iRouterProduct();
routerProduct.start();
routerProduct.setWife();
routerProduct.setting();
System.out.println("===== 華為系列產品 =====");
HuaweiProductFactory huaweiProductFactory = new HuaweiProductFactory();
IPhoneProduct iPhoneProduct2 = huaweiProductFactory.iphoneProduct();
iPhoneProduct2.start();
iPhoneProduct2.callUp();
iPhoneProduct2.sendEmail();
IRouterProduct routerProduct2 = huaweiProductFactory.iRouterProduct();
routerProduct2.start();
routerProduct2.setWife();
routerProduct2.setting();
}
}
小結
- 簡單工廠模式(靜態工廠模式)
雖然某種程度上不符合設計原則,但實際使用最多 - 工廠方法模式
不修改已有類的前提下,通過增加新的工廠類實現擴展。 - 抽象工廠模式
不可以增加產品,可以增加產品族