Rust語言之GoF設計模式:抽象工廠模式
抽象工廠解決了在不指定具體類的情況下建立整個產品系列的問題。
抽象工廠的抽象介面:lib.rs
pub trait Button { fn press(&self); } pub trait Checkbox { fn switch(&self); } /// 抽象工廠是透過泛型實現的,它允許編譯器建立一個不需要在執行時進行動態排程的程式碼。 pub trait GuiFactory { type B: Button; type C: Checkbox; fn create_button(&self) -> Self::B; fn create_checkbox(&self) -> Self::C; } /// 使用Box指標定義的抽象工廠。 pub trait GuiFactoryDynamic { fn create_button(&self) -> Box<dyn Button>; fn create_checkbox(&self) -> Box<dyn Checkbox>; } |
有兩種介面元素:按鈕Button和選擇框CheckBox
然後:
Button按鈕有兩種風格:Windows和MacOs ;
CheckBox有兩種風格:Windows和MacOs .
上述思路是從介面元素切入,那麼如何建立這2X2的組合產品呢?
這需要重新從新的角度切入,以生產建立功能的思路切入,也就是工廠方法思路切入:
Windows和MacOS是比Button和CheckBox更大級別的分類,在這兩個作業系統中,我們可以分別建立Button和CheckBox。
這種建立的產品是兩個以上產品,因此屬於複雜的抽象工廠,不是簡單工廠,簡單工廠只建立一個產品。
我們將Windows風格的按鈕Button和選擇框CheckBox放在一起作為抽象工廠的實現:
windows-gui是抽象工廠一個實現:
use gui::{Button, Checkbox, GuiFactory, GuiFactoryDynamic}; use crate::{button::WindowsButton, checkbox::WindowsCheckbox}; pub struct WindowsFactory; impl GuiFactory for WindowsFactory { type B = WindowsButton; type C = WindowsCheckbox; fn create_button(&self) -> WindowsButton { WindowsButton } fn create_checkbox(&self) -> WindowsCheckbox { WindowsCheckbox } } impl GuiFactoryDynamic for WindowsFactory { fn create_button(&self) -> Box<dyn Button> { Box::new(WindowsButton) } fn create_checkbox(&self) -> Box<dyn Checkbox> { Box::new(WindowsCheckbox) } } |
泛型按鈕B的具體實現button.rs:
use gui::Button; pub struct WindowsButton; impl Button for WindowsButton { fn press(&self) { println!("Windows button has pressed"); } } |
泛型按鈕C的實現:checkbox.rs
use gui::Checkbox; pub struct WindowsCheckbox; impl Checkbox for WindowsCheckbox { fn switch(&self) { println!("Windows checkbox has switched"); } } |
另外一個輔助:lib.rs
以上是Windows風格抽象工廠實現,另外一個是蘋果風格實現:macos-gui,點選見原始碼
客戶端程式碼
抽象工廠的結構基本搭建起來,下面看看魔法的核心在客戶端呼叫處:
下面是呼叫抽象工廠程式碼:main.rs
mod render; use render::render; use macos_gui::factory::MacFactory; use windows_gui::factory::WindowsFactory; fn main() { let windows = true; if windows { render(WindowsFactory); } else { render(MacFactory); } } |
這個main.rs對兩個工廠進行了選擇切換,具體渲染依賴於render.rs:
//! 程式碼表明,它不依賴於具體的 //工廠的實現。 use gui::GuiFactory; // 渲染GUI。工廠物件必須作為一個引數傳遞給這種 工廠呼叫的 //泛型函式,以利用靜態排程。 pub fn render(factory: impl GuiFactory) { let button1 = factory.create_button(); let button2 = factory.create_button(); let checkbox1 = factory.create_checkbox(); let checkbox2 = factory.create_checkbox(); use gui::{Button, Checkbox}; button1.press(); button2.press(); checkbox1.switch(); checkbox2.switch(); } |
在這個渲染方法中,實現了最初功能需求:
Button按鈕有兩種風格:Windows和MacOs ;
CheckBox有兩種風格:Windows和MacOs .
但是,這段程式碼沒有耦合依賴於Windows和MacOs兩個工廠,而只是依賴抽象工廠介面。
那麼抽象工廠與具體兩個工廠實現如何裝配在一起呢?在main.rs這個客戶端呼叫程式碼的if else語句
這樣做的好處:客戶端能根據自已的上下文環境,自由指定不同的工廠實現:
如果當前應用入口是安裝在windows上,就指定windows的工廠建立windows風格的兩種介面元素;
而如果當前應用入口是安裝在MacOs上,就指定MacOS的工廠建立MacOs風格的兩種介面元素;
那麼能不能在客戶端根據自己執行作業系統環境自動選擇工廠呢?不用ifelse這樣虛擬碼?
mod render; use render::render; use gui::GuiFactoryDynamic; use macos_gui::factory::MacFactory; use windows_gui::factory::WindowsFactory; fn main() { let windows = false; // 根據無法預測的輸入,在執行時分配一個工廠物件。 let factory: &dyn GuiFactoryDynamic = if windows { &WindowsFactory } else { &MacFactory }; // 工廠的呼叫可以在這裡被內聯。 let button = factory.create_button(); button.press(); // 工廠物件可以作為引數傳遞給一個函式。 render(factory); } |
總結
這樣,透過抽象工廠,根據不同作業系統建立多個介面元素,如果新增新的作業系統,如Linux,我們只要實現相應工廠實現,在其中實現介面元素的建立,而這個新增程式碼的過程,不涉及對原始碼結構的修改,這樣如同蓋房子,蓋好的結構不用修改,假設鋼筋柱都澆築好了,準備用磚頭砌牆,發現兩個鋼筋柱需要挪移,否則無法砌牆,這在建築上是致命,同理也適合軟體工程。
相關文章
- Rust語言之GoF設計模式:工廠模式RustGo設計模式
- Rust語言之GoF設計模式:靜態工廠RustGo設計模式
- Rust語言之GoF設計模式: 模板方法模式RustGo設計模式
- Rust語言之GoF設計模式:原型模式RustGo設計模式原型
- Rust語言之GoF設計模式:迭代器模式RustGo設計模式
- Rust語言之GoF設計模式:Flyweight享元模式RustGo設計模式
- Rust語言之GoF設計模式:責任鏈模式RustGo設計模式
- Rust語言之GoF設計模式:中介者Mediator模式RustGo設計模式
- Rust語言之GoF設計模式:備忘錄Memento模式RustGo設計模式
- Rust語言之GoF設計模式: 直譯器Interpreter模式RustGo設計模式
- Rust語言之GoF設計模式:介面卡AdapterRustGo設計模式APT
- 設計模式 —— 抽象工廠模式設計模式抽象
- 設計模式-抽象工廠模式設計模式抽象
- 設計模式——抽象工廠模式設計模式抽象
- java設計模式–抽象工廠模式Java設計模式抽象
- Java設計模式-抽象工廠模式Java設計模式抽象
- 設計模式-簡單工廠、工廠方法模式、抽象工廠模式設計模式抽象
- 設計模式 - 抽象工廠設計模式抽象
- 設計模式----抽象工廠設計模式抽象
- 設計模式 – 抽象工廠設計模式抽象
- 設計模式學習(二)工廠模式——抽象工廠模式設計模式抽象
- C# 設計模式(1)——簡單工廠模式、工廠模式、抽象工廠模式C#設計模式抽象
- Java 設計模式之工廠方法模式與抽象工廠模式Java設計模式抽象
- 建立型設計模式——抽象工廠模式設計模式抽象
- golang設計模式之抽象工廠模式Golang設計模式抽象
- 設計模式(三)抽象工廠方法模式設計模式抽象
- 設計模式系列之「抽象工廠模式」設計模式抽象
- 23種設計模式(抽象工廠模式)設計模式抽象
- 設計模式之工廠模式!深入解析簡單工廠模式,工廠方法模式和抽象工廠模式設計模式抽象
- 設計模式--抽象工廠模式(Abstract Factory Pattern)設計模式抽象
- Java常用設計模式之抽象工廠模式Java設計模式抽象
- 設計模式-抽象工廠模式(Abstract Factory Pattern)設計模式抽象
- 設計模式學習(六)-抽象工廠模式設計模式抽象
- GoF之工廠模式Go模式
- JAVA設計模式 3【建立型】理解工廠模式與抽象工廠模式Java設計模式抽象
- Java設計模式學習筆記——工廠模式與抽象工廠模式Java設計模式筆記抽象
- 設計模式學習(二)工廠模式——抽象工廠模式+登錄檔設計模式抽象
- 設計模式——抽象工廠實驗設計模式抽象