淺聊 Rust 【策略 · 設計模式】 Strategy - Policy design pattern

Rust - Strategy / Policy策略 · 模式】與【OOP - Dependency Inversion依賴倒置 · 模式】和【Javascript - Callback Functon回調函數 · 模式】皆同屬一類設計模式組合Inversion of Control + Dependency Injection(控制反轉 + 依賴注入)。爲了描述簡潔,後文將該組合記作:IoC + DI

先上圖(一圖抵千詞)

就着上圖,我再進一步展開論述。

IoC容器

IoC容器內定義

一般IoC容器會對外導出一個pub函數來

DI依賴注入

利用DI從 “業務總線” 上扣出可 · 填入 · 自定義實現細節的“trait坑位” — 非具體類型,避免IoC容器和單一類型 “捆綁”。

作爲 “坑位”,有兩個特質不能少:

trait坑位

IoC容器而言,僅有trait定義裏的

是可見的。另外,因爲rust允許爲trait method提供默認實現,所以trait坑位也能爲自己提供缺省實現項,若調用端 · 程序員沒有注入定製解決方案的話。

trait坑位 · 填充物

首先,在Rust語境中,該 “填充物” 有一個專屬名詞叫作Strategy Structs

其次,【閉包Closure】與【函數指針fn】被允許經由DI接口 · 注入至IoC容器內 · 不是什麼語言 “特例”,而是僅只因爲【閉包Closure】與【函數指針fn】本質上就是實現了Fn / FnMut / FnOnce traitstruct實例。至於它們在字面量上不像struct,那是因爲語法糖:

編譯器真的爲我們做了許多的事情。

最後,憑藉trait實現類的(私有)字段,還能實現

的功能。

IoC + DIrust的技術落地

相對於弱類型的js,強類型的rust

相對於玩轉【堆】的javarust還允許向IoC容器注入複雜數據類型的【棧】變量值,而無論該變量值是被【靜態分派】還是【動態分派】。

於是,我的總結是在rust裏的IoC + DI的設計模式落地 · 比js嚴謹,比java靈活。

綜合性【例程】將知識點串聯起來

該【例程】實現的功能是:

該【例程】代碼分成三個子模塊。它們分別對應IoC + DI設計模式內的三大構件:

  1. IoC容器mod ioc_containerioc_container::Report類型。並且,在ioc_container::Report::generate()關聯函數內定義了

  2. 業務總線

  3. 可複用的功能模塊ioc_container::Report::sign_me()給【報表】生成【數字簽名】。

  4. DI注入標準(也稱trait坑位規格)mod di_spec。只有滿足了該規格要求的struct實例或closure才能被注入到IoC容器內。在本例中,包括:

  5. 如何獲取【源數據】di_spec::Ingredient— 這是一個被動態分派的【閉包】簽名。

  6. 如何格式化【源數據】di_spec::Formatter — 這是一個待實現的trait

  7. DI依賴項(也稱trait坑位 · 填充物)mod di_stuff。在本例中,包括:

  8. 它輸出了可生成【報表 · 源數據】的閉包。

  9. 更重要的是,由此高階函數輸出的閉包滿足了di_spec::Ingredient定義的函數簽名。

  10. 高階函數fn data_builder()

  11. 純文本格式化【源數據】的代碼di_stuff::Text

  12. JSON格式化【源數據】的代碼di_stuff::Json

最後,在main函數內,依次

  1. 實例化DI依賴項

  2. DI依賴項注入IoC容器 — 就是給ioc_container::Report::generate()關聯函數傳參。

  3. 執行 “業務總線” 工作流

  4. 讀取【源數據】,

  5. 格式化【報表】,

  6. 生成【數字簽名】

  7. 獲得一個Report結構體實例。其包括了

  8. 報表的文本內容

  9. 它的數字簽名

思路擴展

【條件編譯】plus【策略 · 設計模式】是一套非常棒的多平臺適配方案。即,

  1. 將【核心業務】中 · 與平臺相關的 · 功能模塊 · 扣成trait坑位。

  2. 給每個trait坑位準備多套 · 適配不同(交叉編譯)目標平臺的 ·Strategy Structs具體實現。

  3. 在編譯時,根據rustc --cfgcargo --features命令行參數,(利用#[cfg(...)]元屬性)將恰當的Strategy Struct(依賴)注入到 · 封裝了核心業務IoC容器裏的trait坑位內。

  4. 輸出兼容於指定平臺的exedll文件。

哎呀!怎麼越講,越像serde crate了。但是,這麼設計真是很【優雅】!

結束語

經由【回調函數】將 · 可定製技術細節 · 甩出【主函數】是一條比較常見的編程套路。可是,一旦給 “土 · 方子” 賦上一個fancy name,好似一切都變得好高端、好抽象、好難理解!所以,我個人提議:將Rust - Strategy設計模式重命名爲更接地氣的和土得掉渣的名字 “回調函數 · 模式”。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/R8BXehVAyR95U6yNj1ZAMw