你好!今天我們繼續學習設計模式,聊聊抽象工廠。 講座期間我們將做什麼:
- 讓我們來討論一下什麼是抽象工廠以及這個模式解決什麼問題;
- 我們將創建一個跨平台應用程式的框架,用於透過使用者介面訂購咖啡;
- 讓我們透過圖表和代碼來研究使用此模式的說明;
- 作為獎勵,講座中隱藏了一個復活節彩蛋,透過它您將學習使用 Java 確定作業系統的名稱,並根據結果執行一個或另一個操作。
- Java中的繼承;
- Java 中的抽象類別和方法。
抽象工廠模式解決了什麼問題?
與所有工廠模式一樣,抽象工廠幫助我們正確組織新物件的創建。在它的幫助下,我們可以管理各種互連物件系列的「發布」。各種相互關聯的物件系列...它是什麼?別擔心:其實一切都比看起來更簡單。讓我們從相關物件系列開始吧?假設你和我正在製定一個策略,其中有幾個戰鬥單元:- 步兵;
- 騎兵;
- 弓箭手。
我們持續實現咖啡店的自動化
在上一講中,我們學習了工廠方法模式,借助它我們能夠擴展咖啡業務並開設幾個新的咖啡銷售點。今天,我們將繼續努力實現業務現代化。使用抽象工廠模式,我們將為在線訂購咖啡的新桌面應用程式奠定基礎。當我們為桌面編寫應用程式時,我們應該始終考慮跨平台。我們的應用程式應該可以在 macOS 和 Windows 上運行(劇透:Linux 將留給您作為家庭作業)。我們的應用程式會是什麼樣子?非常簡單:它將是一個由文字欄位、選擇欄位和按鈕組成的表單。如果您有使用不同作業系統的經驗,您一定會注意到 Windows 上的按鈕呈現方式與 Mac 上不同。就像其他一切一樣......所以,讓我們開始吧。正如您可能已經了解的那樣,在產品系列的角色中,我們將擁有圖形介面元素:- 紐扣;
- 文字欄位;
- 供選擇的欄位。
onClick
、onValueChanged
或 之類的方法onInputChanged
。那些。允許我們處理各種事件的方法(點擊按鈕、輸入文字、在選擇框中選擇值)。所有這些都被故意省略,以免示例超載並使其對於研究工廠模式更加直觀。讓我們為我們的產品定義抽象介面:
public interface Button {}
public interface Select {}
public interface TextField {}
對於每個作業系統,我們必須以該作業系統的風格建立介面元素。我們為 Windows 和 MacOS 編寫。讓我們為 Windows 建立實作:
public class WindowsButton implements Button {
}
public class WindowsSelect implements Select {
}
public class WindowsTextField implements TextField {
}
現在 MacOS 也是一樣:
public class MacButton implements Button {
}
public class MacSelect implements Select {
}
public class MacTextField implements TextField {
}
偉大的。現在我們可以啟動我們的抽象工廠,它將創建所有現有的抽象產品類型:
public interface GUIFactory {
Button createButton();
TextField createTextField();
Select createSelect();
}
完美的。如您所見,到目前為止沒有什麼複雜的。那麼一切就這麼簡單了。透過與產品類比,我們為每個作業系統創建了不同的工廠實現。讓我們從 Windows 開始:
public class WindowsGUIFactory implements GUIFactory {
public WindowsGUIFactory() {
System.out.println("Creating gui factory for Windows OS");
}
public Button createButton() {
System.out.println("Creating Button for Windows OS");
return new WindowsButton();
}
public TextField createTextField() {
System.out.println("Creating TextField for Windows OS");
return new WindowsTextField();
}
public Select createSelect() {
System.out.println("Creating Select for Windows OS");
return new WindowsSelect();
}
}
新增了方法和建構函數內的控制台輸出,以進一步演示其工作原理。現在對於 macOS:
public class MacGUIFactory implements GUIFactory {
public MacGUIFactory() {
System.out.println("Creating gui factory for macOS");
}
@Override
public Button createButton() {
System.out.println("Creating Button for macOS");
return new MacButton();
}
@Override
public TextField createTextField() {
System.out.println("Creating TextField for macOS");
return new MacTextField();
}
@Override
public Select createSelect() {
System.out.println("Creating Select for macOS");
return new MacSelect();
}
}
注意:每個方法根據其簽名傳回抽象類型。但在方法內部,我們創造了產品的具體實作。這是我們控制特定實例創建的唯一地方。現在是時候編寫表單類別了。這是一個 Java 類,其欄位是介面元素:
public class OrderCoffeeForm {
private final TextField customerNameTextField;
private final Select coffeTypeSelect;
private final Button orderButton;
public OrderCoffeeForm(GUIFactory factory) {
System.out.println("Creating order coffee form");
customerNameTextField = factory.createTextField();
coffeTypeSelect = factory.createSelect();
orderButton = factory.createButton();
}
}
抽象工廠被傳遞給表單建構函數,該構造函數會建立介面元素。我們將所需的工廠實作傳遞給建構函數,以便我們可以為特定作業系統建立介面元素。
public class Application {
private OrderCoffeeForm orderCoffeeForm;
public void drawOrderCoffeeForm() {
// Определим Name операционной системы, получив meaning системной проперти через System.getProperty
String osName = System.getProperty("os.name").toLowerCase();
GUIFactory guiFactory;
if (osName.startsWith("win")) { // Для windows
guiFactory = new WindowsGUIFactory();
} else if (osName.startsWith("mac")) { // Для mac
guiFactory = new MacGUIFactory();
} else {
System.out.println("Unknown OS, can't draw form :( ");
return;
}
orderCoffeeForm = new OrderCoffeeForm(guiFactory);
}
public static void main(String[] args) {
Application application = new Application();
application.drawOrderCoffeeForm();
}
}
如果我們在 Windows 上運行該應用程序,我們將得到以下輸出:
Creating gui factory for Windows OS
Creating order coffee form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
在 Mac 上,輸出如下:
Creating gui factory for macOS
Creating order coffee form
Creating TextField for macOS
Creating Select for macOS
Creating Button for macOS
在 Linux 上:
Unknown OS, can't draw form :(
好吧,你和我得出以下結論。我們為 GUI 應用程式編寫了一個框架,該框架準確地創建了適合給定作業系統的介面元素。讓我們簡單地重複一下我們創建的內容:
- 產品系列:輸入欄位、選擇欄位和按鈕。
- 此系列產品的各種實現,適用於 Windows 和 macOS。
- 一個抽象工廠,我們在其中定義了用於創建產品的介面。
- 我們工廠的兩個實現,每個實現負責創建特定的產品系列。
- 一個表單,一個 Java 類,其欄位是抽象介面元素,這些元素在建構函式中使用抽象工廠用所需的值進行初始化。
- 應用類。在其中,我們建立一個表單,透過該表單將工廠所需的實作傳遞給建構函式。
抽象工廠:使用說明
抽象工廠是一種設計模式,用於管理不同產品系列的創建,而不依賴特定的產品類別。使用此範本時,您必須:- 自行定義產品系列。假設我們有兩個:
SpecificProductA1
,SpecificProductB1
SpecificProductA2
,SpecificProductB2
- 對於該系列中的每個產品,定義一個抽象類別(介面)。在我們的例子中是:
ProductA
ProductB
- 在每個產品系列中,每個產品都必須實作步驟 2 中定義的介面。
- 建立一個抽象工廠,並為步驟 2 中定義的每個產品建立方法。在我們的例子中,這些方法將是:
ProductA createProductA();
ProductB createProductB();
- 創建抽象工廠的實現,以便每個實現控制同一系列產品的創建。為此,在抽象工廠的每個實作中,有必要實作所有創建方法,以便在其中創建並返回產品的具體實作。
// Определим общие интерфейсы продуктов
public interface ProductA {}
public interface ProductB {}
// Создадим различные реализации (семейства) наших продуктов
public class SpecificProductA1 implements ProductA {}
public class SpecificProductB1 implements ProductB {}
public class SpecificProductA2 implements ProductA {}
public class SpecificProductB2 implements ProductB {}
// Создадим абстрактную фабрику
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
public class SpecificFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new SpecificProductA1();
}
@Override
public ProductB createProductB() {
return new SpecificProductB1();
}
}
// Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
public class SpecificFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new SpecificProductA2();
}
@Override
public ProductB createProductB() {
return new SpecificProductB2();
}
}
家庭作業
要整合材料,您可以做兩件事:- 改進咖啡訂購應用程序,使其可以在 Linux 上運行。
- 創建您自己的抽象工廠來生產任何策略的單元。這既可以是真實軍隊的歷史策略,也可以是獸人、矮人和精靈的幻想。最主要的是你覺得有趣。發揮創意,將圖釘發佈到控制台,並享受學習模式的樂趣!
GO TO FULL VERSION