抽象工廠模式 Abstract Factory Pattern

989 字
5 分鐘
抽象工廠模式 Abstract Factory Pattern

目的#

同一個介面建立一整族相關的物件,不需點明各物件真正所屬的實體類別。

適用#

  • 使用者無法預測要實例化的Class時。系統必須與最終Product的生成、組合、表達方式保持獨立。能讓各陣營的Product和系統互相搭配時使用,並且需要強制約束這件事。一整族相關物件由相同Factory生成,確保不會搭配錯誤。你把類別函式庫貢獻出來,但只想公開介面,不想公開實作細節。

結構及成員#

Collaborations: 在執行期,ConcreteFactory只有單獨一個,如果想生成其他陣營的,就要換另一種ConcreteFactory。AbstractFactory將製造Product的責任交付給子類別ConcreteFactory處理。

  • AbstractFactory: like the GUIFactory, WidgetFactory此Interface宣告出可生成各抽象成品物件的方法。ConcreteFactory: like the MotifFactory, PMWWidgetFactory.實作出可產生實體Product物件的方法。AbstractProduct: like the ScrollBar, AbstractProductA宣告某成品物件類型之介面。ConcreteProduct: like the MotifScrollBar, PMScrollBarConcreteFactory 所建構的成品物件。AbstractProduct 介面的實體實作。Client只觸及AbstractFactory和AbstractProduct兩抽象類別所訂之介面。

影響結果#

好處#

  • 將實體類別隔離開來,Product類別都被ConcreteFactory藏了起來,Client無從得知。易於將整族成品物件抽換掉,因為AbstractFactory可生成一整族成品物件,所以只要換成其他Factory,就能一舉將成品物件組態整個換掉。增進成品物件的一致性。

壞處#

  • 難以提供新的成品物件種類,讓AbstractFactory產生新的Product類型,不是容易的事,得修改AbstractFatory類別及所有子類別。

實作#

將Factory做成Singleton#

正常情況下,應用程式只需對一族(陣營)的Product配一個ConcreteFactory,因此最好做成Singleton Pattern。

產生成品物件#

  • AbstractFactory只含製造Product的介面而已,實作是由各ConcreteFactory子類別負責。常見做法是一種Product定義一種Method,然後ConcreteFactory可以Override各自的Method。如果會有好幾族成品物件同時並存,可以採用Prototype Pattern來製作ConcreteFactory。(先將各族系各成品弄一個Prototype物件給ConcreteFactory,以複製Prototype的方式製作新成品)

定義可延伸的Factory#

AbstractFactory通常會替每種可能產生的物件定義方法,若想增加新Product類型,就得修改有牽連的類別,因此可使用Make搭配參數來決定該建造哪種Product

Example: Parser#

//Abstra: AbstractParserFactory
public interface AbstractParserFactory {
public XMLParser getParserInstance(String parserType);
}
//Class: Interface XMLParser
public interface XMLParser {
public String parse();
}
//Class: ParserFactoryProducer
public final class ParserFactoryProducer {
private ParserFactoryProducer(){
throw new AssertionError();
}
public static AbstractParserFactory getFactory(String factoryType){
switch(factoryType)
{
case "NYFactory": return new NYParserFactory();
case "TWFactory": return new TWParserFactory();
}
return null;
}
}
//Class: NYParserFactory
public class NYParserFactory implements AbstractParserFactory {
@Override
public XMLParser getParserInstance(String parserType) {
switch(parserType){
case "NYERROR": return new NYErrorXMLParser();
case "NYFEEDBACK": return new NYFeedbackXMLParser();
case "NYORDER": return new NYOrderXMLParser();
case "NYRESPONSE": return new NYResponseXMLParser();
}
return null;
}
}
//Class: NYErrorXMLParser
public class NYErrorXMLParser implements XMLParser{
@Override
public String parse() {
System.out.println("NY Parsing error XML...");
return "NY Error XML Message";
}
}
//Class: NYFeedbackXMLParser
public class NYFeedbackXMLParser implements XMLParser{
@Override
public String parse() {
System.out.println("NY Parsing feedback XML...");
return "NY Feedback XML Message";
}
}
//Class: NYOrderXMLParser
public class NYOrderXMLParser implements XMLParser{
@Override
public String parse() {
System.out.println("NY Parsing order XML...");
return "NY Order XML Message";
}
}
//Class: NYResponseParser
public class NYResponseXMLParser implements XMLParser{
@Override
public String parse() {
System.out.println("NY Parsing response XML...");
return "NY Response XML Message";
}
}
//Class: TWParserFactory
public class TWParserFactory implements AbstractParserFactory {
@Override
public XMLParser getParserInstance(String parserType) {
switch(parserType){
case "TWERROR": return new TWErrorXMLParser();
case "TWFEEDBACK": return new TWFeedbackXMLParser();
case "TWORDER": return new TWOrderXMLParser();
case "TWRESPONSE": return new TWResponseXMLParser();
}
return null;
}
}
//Class: TWErrorXMLParser
public class TWErrorXMLParser implements XMLParser{
@Override
public String parse() {
System.out.println("TW Parsing error XML...");
return "TW Error XML Message";
}
}
//Class: TWFeedbackXMLParser
public class TWFeedbackXMLParser implements XMLParser{
@Override
public String parse() {
System.out.println("TW Parsing feedback XML...");
return "TW Feedback XML Message";
}
}
//Class: TWOrderXMLParser
public class TWOrderXMLParser implements XMLParser{
@Override
public String parse() {
System.out.println("TW Parsing order XML...");
return "TW Order XML Message";
}
}
//Class: TWResponseXMLParser
public class TWResponseXMLParser implements XMLParser{
@Override
public String parse() {
System.out.println("TW Parsing response XML...");
return "TW Response XML Message";
}
}
//Class: TestAbstractFactoryPattern
public class TestAbstractFactoryPattern {
public static void main(String[] args) {
AbstractParserFactory parserFactory = ParserFactoryProducer.getFactory("NYFactory");
XMLParser parser = parserFactory.getParserInstance("NYORDER");
String msg="";
msg = parser.parse();
System.out.println(msg);
System.out.println("************************************");
parserFactory = ParserFactoryProducer.getFactory("TWFactory");
parser = parserFactory.getParserInstance("TWFEEDBACK");
msg = parser.parse();
System.out.println(msg);
}
}
Result:
NY Parsing order XML...
NY Order XML Message
************************************
TW Parsing feedback XML...
TW Feedback XML Message

文章分享

如果這篇文章對你有幫助,歡迎分享給更多人!

抽象工廠模式 Abstract Factory Pattern
https://linziyou.info/posts/2020-09-30-抽象工廠模式-abstract-factory-pattern/
作者
Lin Ziyou
發布於
2020-09-30
許可協議
CC BY-NC-SA 4.0
最後更新於 2020-09-30,距今已過 1979 天

部分內容可能已過時

Profile Image of the Author
Lin Ziyou
Hi! I'm Jerry~
分類
標籤
站點統計
文章
45
分類
8
標籤
10
總字數
43,470
運作天數
0
最後活動
0 天前

目錄