👈?上一篇:單例模式 ? ?|?? 下一篇:抽象工廠模式👉?
目錄
- 工廠方法模式
- 概覽
- 工廠方法模式的定義
- 英文原話
- 直譯
- 工廠方法模式的4個角色
- 抽象工廠(Creator)角色
- 具體工廠(Concrete Creator)角色
- 抽象產品(Product)角色
- 具體產品(Concrete Product)角色
- 類圖
- 代碼示例
- 抽象工廠Creator.java
- 具體工廠ConcreteCreator.java
- 抽象產品Product.java
- 具體產品ConcreteProduct.java
- 應用代碼ClientFactoryMethodDemo.java
- 工廠方法模式的應用
- 工廠方法模式的優點
- 工廠方法模式的使用場景
- 工廠方法模式的示例解析
- 類圖
- 1. 抽象工廠類:FruitGardener.java(果子園接口,生產各類水果的)
- 2. 具體工廠類:
- 2.1 具體的某果園:AppleGardener.java (蘋果園類,生產蘋果)
- 2.2 具體的某果園:GrapeGardener.java(葡萄園類,生產葡萄)
- 3. 抽象產品類:Fruit.java(水果接口,抽象的水果類)
- 4. 具體產品類:
- 4.1 具體的某類水果:Apple.java(蘋果類,是一種具體的水果)
- 4.2 具體的某類水果:Grape.java(葡萄類,是一種具體的水果)
- 5. 測試類
工廠方法模式
工廠方法模式(Factory Method Pattern)又叫虛擬構造函數(Virtual Constructor)模式
或者多態性工廠(PolymorphicFactory)模式。工廠方法模式的用意是定義一個創建產品對象
的工廠接口,將實際創建性工作推遲到子類中。
工廠模式可分為簡單工廠、工廠方法和抽象工廠模式。
- 簡單工廠模式中,一個工廠類處于對產品類實例化的中心位置上,它知道每一個產品,它決定哪一個產品類應當被實例化。
這個模式的優點是允許客戶端相對獨立于產品創建的過程,并且在系統引入新產品的時候無須修改客戶端,即在某種程度上支持“開-閉”原則(一個軟件實體應當對擴展開放,對修改關閉)。
這個模式的缺點是對 “開-閉” 原則的支持不夠,因為如果有新的產品加入到系統中,則需要修改工廠類,將必要的邏輯加入到工廠類中。
- 工廠方法模式是簡單工廠模式的進一步抽象和推廣。由于使用了多態性,工廠方法模式保持了簡單工廠模式的優點,且克服了它的缺點。
首先,在工廠方法模式中,核心的工廠類不再負責所有產品的創建,而是將具體創建的工作交給子類去做。這個核心類則成為一個抽象工廠角色,僅負責給出具體工廠子類必須實現的接口,而不接觸哪個產品類應當被實例化的細節。此種進一步抽象化的結果,使這種工廠方法模式可以用來允許系統在不修改具體工廠角色的情況下引進新的產品,這一特點使得工廠模式具有超過簡單工廠的優越性。
-
抽象工廠模式是所有形態的工廠模式中最為抽象和最具有一般性的一種形態。
抽象工廠模式與工廠方法模式的最大區別就在于,工廠方法模式針對的是一個產品等級結構;而抽象工廠模式則需要面對多個產品等級結構。
概覽
-
工廠方法模式的定義
-
工廠方法模式的4個角色
-
工廠方法模式的應用
- 工廠方法模式的優點
- 工廠方法模式的使用場景
-
工廠方法模式的示例解析
-
待辦:工廠方法模式的使用場景 第三條/第四條
工廠方法模式的定義
英文原話
Define an interface for creating an object, but let subclasses decide which class to instantiate. FactoryMethod lets a class defer instantiation to subclasses.
直譯
意思是:定義一個用于創建對象的接口,讓子類決定實例化哪個類。工廠方法使一個類的實例化延遲到其子類。
工廠方法模式的4個角色
抽象工廠(Creator)角色
該角色是工廠方法模式的核心,與應用系統無關,任何在創建對象的工廠類必須實現這個接口。
具體工廠(Concrete Creator)角色
該角色實現了抽象工廠接口,含有與應用密切相關的邏輯,并且受到應用程序的調用以創建產品對象。
抽象產品(Product)角色
該角色負責定義產品的共性,實現對產品最抽象的定義。
具體產品(Concrete Product)角色
該角色實現抽象產品角色所聲明的接口,工廠方法模式所創建的每一個對象都是某個具體產品角色的實例。
類圖
代碼示例
示例代碼
抽象工廠Creator.java
public interface Creator {//工廠方法//創建一個產品對象,其輸入參數類型可自行設置public <T extends Product> T factory(Class<T> c);
}
具體工廠ConcreteCreator.java
public class ConcreteCreator implements Creator {@Overridepublic <T extends Product> T factory(Class<T> c) {Product product = null;try {product= (Product) Class.forName(c.getName()).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return (T) product;}
}
抽象產品Product.java
public interface Product {//產品類的公共方法public void method1();public void method2();
}
具體產品ConcreteProduct.java
public class ConcreteProduct implements Product {@Overridepublic void method1() {//業務邏輯處理代碼System.out.println("test method1()");}@Overridepublic void method2() {//業務邏輯處理代碼}
}
應用代碼ClientFactoryMethodDemo.java
public class ClientFactoryMethodDemo {public static void main(String[] args) {Creator creator = new ConcreteCreator();Product product = creator.factory(ConcreteProduct.class);//繼續業務處理product.method1();}
}
[注]:上述通用代碼是一個比較實用的、易擴展的框架,可以根據實際項目需要進行擴展應用。
工廠方法模式的應用
工廠方法模式的優點
- 良好的封裝性,代碼結構清晰。一個對象創建是有條件約束的,如果一個調用者需要一個具體的產品對象,
只要知道這個產品的類名或約束字符串即可,不用知道創建對象的過程如何,降低了模塊間的耦合。 - 優秀的可擴展性。在增加產品類的情況下,只要適當地修改具體的工廠類或擴展一個工廠類,就可以適應變化。
- 屏蔽產品類。產品類的實現如何變化,調用者都不需要關心,而只需要關心產品的接口,只要接口保持不變,
系統的上層模塊就不需要發生變化。因為產品的實例化是由工廠類負責的,具體生產何種產品對象是由不同的工廠類
決定的。 - 工廠方法模式是典型的解耦框架。高層模塊只需要知道產品的抽象類,其他的實現類都不用關心。
工廠方法模式符合迪米特法則 (又叫最少知識原則(Least Knowledge Principle,LKP).
只與你直接的朋友們通信(Only talk to your immediatefriends);
不要跟“陌生人”說話(Don’t talk to strangers);),也符合依賴倒置原則
(高層模塊不應該依賴低層模塊,兩者都依賴其抽象;抽象不依賴細節 細節應該依賴于抽象。),只依賴產品類的抽象;
另外還符合里氏替換原則,可以使用產品子類替換產品父類。
工廠方法模式的使用場景
工廠方法模式在項目中使用得非常頻繁,在很多框架的代碼中都可以發現工廠方法模式的應用。可使用工廠方法模式的典型場景如下。
- 工廠方法模式是new一個對象的替代品,因此在所有需要生成對象的地方都可以使用,
但是需要慎重考慮是否需要增加一個工廠類進行管理,增加代碼的復雜度。 - 需要靈活的、可擴展的框架時,可以考慮采用工廠方法模式。
- 工廠方法模式可以用在異構項目中,例如,通過WebService與一個非Java的項目交互,雖然WebService號稱是可以做到異構系統的同構化,但是在實際開發中,還是會碰到很多問題,如類型問題、WSDL文件的支持問題等。從WSDL中產生的對象都認為是一個產品,然后由一個具體的工廠類進行管理,減少與外圍的耦合。
- 工廠方法模式可以使用在測試驅動開發的框架下。例如,測試一個類 A,就需要將與類A關聯的類B也同時產生出來,使用工廠方法模式可以將類B虛擬出來,避免類A與類B的耦合。
- [注]:工廠方法模式還可以與其他模式混合使用(如模板方法模式、單例模式、原型模式等),從而構造出擴展性更好的設計。
工廠方法模式的示例解析
代碼示例
通過農場系統演示工廠方法模式的應用(但是工廠方法模式只能針對一個產品等級結構如A產品B產品。但是如果是A產品與B產品的第一等級第二等級,這種情況要抽象工廠模式。)
類圖
1. 抽象工廠類:FruitGardener.java(果子園接口,生產各類水果的)
package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 水果園丁FruitGardener接口是抽象工廠** @author Polaris 2024/5/16*/
public interface FruitGardener {Fruit factory();
}
2. 具體工廠類:
2.1 具體的某果園:AppleGardener.java (蘋果園類,生產蘋果)
該具體工廠-蘋果園工廠,封裝了實例化具體產品-蘋果對象的過程
package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 蘋果園丁AppleGardener實現FruitGardener接口,是一個用于生產蘋果的具體工廠** @author Polaris 2024/5/16*/
public class AppleGardener implements FruitGardener {@Overridepublic Fruit factory() {return new Apple();}
}
2.2 具體的某果園:GrapeGardener.java(葡萄園類,生產葡萄)
該具體工廠-葡萄園工廠,封裝了實例化具體產品-葡萄對象的過程
package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 葡萄園丁GrapeGardener實現FruitGardener接口,是一個用于生產葡萄的具體工廠** @author Polaris 2024/5/16*/
public class GrapeGardener implements FruitGardener {@Overridepublic Fruit factory() {return new Grape();}
}
3. 抽象產品類:Fruit.java(水果接口,抽象的水果類)
package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 水果Fruit接口是抽象產品** @author Polaris 2024/5/16*/
public interface Fruit {//生長void grow();//收獲void harvest();//栽種void plant();
}
4. 具體產品類:
4.1 具體的某類水果:Apple.java(蘋果類,是一種具體的水果)
由于蘋果是一類具體的水果類,因此它對抽象的水果類進行了實現,當然同時它也有獨自屬于它自己的方法。
package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 蘋果Apple實現Fruit接口,是一個具體產品** @author Polaris 2024/5/16*/
public class Apple implements Fruit {private int treeAge;public int getTreeAge() {return treeAge;}public void setTreeAge(int treeAge) {this.treeAge = treeAge;}@Overridepublic void grow() {System.out.println("蘋果樹在生長");}@Overridepublic void harvest() {System.out.println("收獲蘋果");}@Overridepublic void plant() {System.out.println("栽種蘋果");}
}
4.2 具體的某類水果:Grape.java(葡萄類,是一種具體的水果)
由于葡萄是一類具體的水果類,因此它對抽象的水果類進行了實現,當然同時它也有獨自屬于它自己的方法。
package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 葡萄Grape實現Fruit接口,是一個具體產品** @author Polaris 2024/5/16*/
public class Grape implements Fruit {private boolean seedless;public boolean isSeedless(){return seedless;}public void setSeedless(boolean seedless){this.seedless=seedless;}@Overridepublic void grow() {System.out.println("葡萄正在生長...");}@Overridepublic void harvest() {System.out.println("收獲葡萄");}@Overridepublic void plant() {System.out.println("栽種葡萄");}
}
5. 測試類
具體某類水果工廠來生產對應的某水果對象,
該水果對象是某具體水果類的實例,
而該具體水果實例實現了抽象的水果類,
里氏替換原則,父類的引用可以指向子類實例,因為子類類型一定是父類類型(或者實現的接口的類型)
package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 下面是一個應用場景代碼** @author Polaris 2024/5/16*/
public class ClientDemo {public static void main(String[] args) {//蘋果園丁工廠FruitGardener fruitGardener = new AppleGardener();//通過工廠生產蘋果Fruit apple = fruitGardener.factory();apple.plant();apple.grow();apple.harvest();fruitGardener = new GrapeGardener();//通過工廠生產葡萄Fruit grape = fruitGardener.factory();grape.plant();grape.grow();grape.harvest();}
}
👈?上一篇:單例模式 ? ?|?? 下一篇:抽象工廠模式👉?