luckyegg168/rust-skill

rust-design-patterns

Rust 慣用設計模式技能。涵蓋 Builder Pattern(型別安全構建器)、 Newtype Pattern(型別封裝與 Deref)、Typestate Pattern(編譯期狀態機)、 RAII Guard Pattern(資源管理)、Interior Mutability(Cell/RefCell/Mutex)、 Strategy Pattern(trait objects vs enum dispatch)、 Command Pattern、Observer Pattern(回呼與事件系統)、…

Quelltext ansehen

Verwendung

  1. Installationsbefehl kopieren und das Quellpaket vor der Installation in der eigenen Agentenumgebung prüfen.
  2. Benötigte Werkzeuge, Zugangsdaten und Hosts im Original prüfen.
  3. Eingabe und gewünschtes Ergebnis beschreiben und die Ausgabe mit den Quellen abgleichen.
npx skills add https://github.com/luckyegg168/rust-skill --skill rust-design-patterns

Vor dem Start

  • Die Installation umfasst weder Modellabo noch API-Kontingent oder Dateizugriffsrechte.
  • Sterne und Installationen zeigen Aktivität, keine unabhängige Qualitäts- oder Sicherheitsprüfung.
Originales Skill-Dokument

Aus dem Quell-Repository gerendert; Überschriften, Beispiele, Code, Tabellen, Links und Bilder bleiben erhalten.

Rust 慣用設計模式

適用場景

  • 設計新的 struct/API 時,需要選擇合適的建構方式(Builder / Typestate)
  • 需要對原始型別加上語意約束或防止混用(Newtype)
  • 管理需要確定釋放的資源(檔案、鎖、連線)→ RAII Guard
  • 在不可變結構中仍需局部可變性 → Interior Mutability
  • 需要執行時多態策略切換 → Strategy(trait object / enum dispatch)
  • 限制 trait 只能在本 crate 實作 → Sealed Trait
  • 為外部型別追加方法 → Extension Trait
  • 事件驅動回呼架構 → Observer / Command Pattern
  • 型別間慣用轉換 → From / Into / TryFrom

核心知識

模式索引表

模式用途複雜度
Newtype為既有型別建立語意包裝,防止混用★☆☆
From/Into型別間慣用零成本轉換★☆☆
Builder (基礎)多欄位 struct 的鏈式建構★★☆
Typestate Builder編譯期強制必填欄位順序★★★
RAII Guard利用 Drop 自動釋放資源★★☆
Interior Mutability在 &self 下進行可變操作★★☆
Strategy (trait object)執行時動態切換行為★★☆
Strategy (enum dispatch)靜態分派、無堆積配置★★☆
Sealed Trait限制 trait 只能在本 crate 實作★★☆
Extension Trait為外部型別追加方法★☆☆
Observer / Callback事件訂閱與通知★★★
Command將操作封裝為物件,支援 undo★★☆

各模式詳解

1. Newtype Pattern

將原始型別包進單欄位 tuple struct,獲得:

  • 型別安全:UserId(u64) 與 OrderId(u64) 編譯期不可混用
  • 封裝:可為 newtype 實作自訂方法與 trait
  • 零成本:編譯後與原始型別完全相同的記憶體佈局
rust
// 基本定義
struct Meters(f64);
struct Seconds(f64);

// 透過 Deref 暴露內部值(謹慎使用)
impl std::ops::Deref for Meters {
    type Target = f64;
    fn deref(&self) -> &f64 { &self.0 }
}

搭配 From/Into:提供慣用的型別轉換,避免手動 .0 存取。

rust
impl From<f64> for Meters {
    fn from(v: f64) -> Self { Meters(v) }
}
// 自動獲得 Into<Meters> for f64

2. Builder Pattern(基礎)

適用於有多個可選欄位的 struct:

rust
struct Config {
    host: String,
    port: u16,
    max_retries: u32,
}

struct ConfigBuilder {
    host: String,
    port: u16,
    max_retries: u32,
}

impl ConfigBuilder {
    fn new(host: impl Into<String>) -> Self { /* ... */ }
    fn port(mut self, port: u16) -> Self { self.port = port; self }
    fn max_retries(mut self, n: u32) -> Self { self.max_retries = n; self }
    fn build(self) -> Config { /* ... */ }
}

也可使用 typed-builder crate 以 derive macro 自動生成。

3. Typestate Builder

利用泛型參數的零大小型別 (ZST) 在編譯期追蹤狀態:

rust
struct NoHost;
struct HasHost;

struct RequestBuilder<H> {
    host: Option<String>,
    _state: std::marker::PhantomData<H>,
}

impl RequestBuilder<NoHost> {
    fn host(self, h: impl Into<String>) -> RequestBuilder<HasHost> { /* 狀態轉移 */ }
}

impl RequestBuilder<HasHost> {
    fn send(self) -> Response { /* 只有設定 host 後才能呼叫 */ }
}

優點:錯誤在編譯期捕獲,不需 runtime 檢查。

4. RAII Guard Pattern

Rust 的 Drop trait 保證離開作用域時自動執行清理:

rust
struct TimerGuard { start: std::time::Instant, label: String }

impl Drop for TimerGuard {
    fn drop(&mut self) {
        println!("{}: {:?}", self.label, self.start.elapsed());
    }
}

常見用途:MutexGuard、檔案鎖、計時器、交易回滾。

5. Interior Mutability

型別執行緒安全檢查時機典型場景
Cell<T>否編譯期(Copy)簡單計數器
RefCell<T>否執行時借用圖結構、快取
Mutex<T>是執行時鎖多執行緒共享
RwLock<T>是讀寫鎖讀多寫少
OnceCell/LazyLock是僅初始化一次全域單例
rust
use std::cell::RefCell;

struct Cache {
    data: RefCell<HashMap<String, String>>,
}

impl Cache {
    fn get_or_insert(&self, key: &str) -> String {
        // &self 但可修改內部 data
        let mut map = self.data.borrow_mut();
        map.entry(key.to_owned())
            .or_insert_with(|| expensive_compute(key))
            .clone()
    }
}

6. Strategy Pattern

Trait object 版本(動態分派,適合插件架構):

rust
trait Compressor: Send + Sync {
    fn compress(&self, data: &[u8]) -> Vec<u8>;
}

fn process(compressor: &dyn Compressor, data: &[u8]) -> Vec<u8> {
    compressor.compress(data)
}

Enum dispatch 版本(無堆積配置,效能更佳):

rust
enum Compressor { Gzip, Lz4, Zstd }

impl Compressor {
    fn compress(&self, data: &[u8]) -> Vec<u8> {
        match self {
            Self::Gzip => { /* ... */ }
            Self::Lz4  => { /* ... */ }
            Self::Zstd => { /* ... */ }
        }
    }
}

選擇原則:變體固定 → enum;需外部擴展 → trait object。

7. Sealed Trait Pattern

防止下游 crate 實作你的 trait:

rust
mod private { pub trait Sealed {} }

pub trait MyTrait: private::Sealed {
    fn method(&self);
}

// 僅在本 crate 內實作 Sealed → 外部無法實作 MyTrait
impl private::Sealed for MyStruct {}
impl MyTrait for MyStruct { fn method(&self) { /* ... */ } }

8. Extension Trait Pattern

為外部型別追加方法而不需要 Newtype:

rust
pub trait StrExt {
    fn is_blank(&self) -> bool;
}

impl StrExt for str {
    fn is_blank(&self) -> bool {
        self.trim().is_empty()
    }
}
// 使用:use crate::StrExt; "  ".is_blank()

9. Observer / Callback Pattern

rust
type Callback<T> = Box<dyn Fn(&T) + Send + 'static>;

struct EventBus<T> {
    listeners: Vec<Callback<T>>,
}

impl<T> EventBus<T> {
    fn subscribe(&mut self, cb: impl Fn(&T) + Send + 'static) {
        self.listeners.push(Box::new(cb));
    }
    fn emit(&self, event: &T) {
        for listener in &self.listeners {
            listener(event);
        }
    }
}

10. Command Pattern

rust
trait Command {
    fn execute(&mut self);
    fn undo(&mut self);
}

將操作封裝為實作 Command 的結構體,支援 undo/redo 堆疊。

程式碼範例

完整可編譯範例見 examples/ 目錄:

  • basic.rs — Newtype + From/Into + Builder(基礎版)
  • intermediate.rs — Typestate Builder + RAII Guard + Interior Mutability
  • advanced.rs — Strategy (trait object + enum) + Sealed Trait + Extension Trait + Observer

常見錯誤對照表

錯誤訊息原因修復方式
the trait Sealed is not implemented for MyType嘗試在外部 crate 實作 Sealed Trait這是設計意圖;改用該 crate 提供的型別
already borrowed: BorrowMutError (runtime panic)RefCell 同時存在 borrow() 與 borrow_mut()縮小借用範圍,或改用 Cell<T> / Mutex<T>
cannot move out of self which is behind a mutable referenceBuilder 方法用 &mut self 但嘗試消耗 self改用 self(owned)作為 builder 方法接收者
unused type parameter HTypestate 泛型參數未被實際欄位使用新增 PhantomData<H> 欄位
trait objects cannot have associated functionstrait 內含 fn new() -> Self 等方法,無法做 dyn Trait加上 where Self: Sized 或移至 companion function
cannot return reference to temporary valueRAII guard 的 Deref 回傳了臨時值的參考確保 guard 內部持有擁有權的資料,Deref 回傳其參考
the trait bound Send is not satisfied將 Rc<RefCell<T>> 用於多執行緒改用 Arc<Mutex<T>>

Cargo.toml 依賴模板

toml
[dependencies]
# derive_more 2.0:自動產生 From, Deref, Display 等 derive
derive_more = { version = "2.0", features = ["from", "deref", "display"] }

# typed-builder:以 derive macro 生成型別安全 builder
typed-builder = "0.20"

# 以下為選用
thiserror = "2"       # 錯誤型別 derive
once_cell = "1.20"    # LazyLock 替代方案(std 已有 LazyLock,此為向後相容)

參考來源

  1. Rust Design Patterns Book — 社群維護的模式集
  2. The Rust Book — Ch.17 OOP Features — trait objects 與動態分派
  3. Rust API Guidelines — Type Safety — Newtype 與型別安全
  4. Cliffle — Typestate Pattern — Typestate 深入教學
  5. Rust Reference — Drop — RAII 與 Drop 語意
  6. derive_more 文件 — 自動 derive 工具
  7. typed-builder 文件 — 型別安全 Builder derive

Verwandte Aufgaben

aus demselben Repository

Weitere Skills

Alle Skills
luckyegg168
Community

rust-async-runtime

Rust 非同步執行時技能。涵蓋 tokio 1.44 runtime 架構與選擇、async/await 語法模式、 Future trait 原理、常見陷阱(blocking in async、async trait)、 channel 通訊(mpsc/oneshot/broadcast/watch)、task spawn 策略、 select! 多路複用、graceful shutdown、async stream、Mutex 在 async 中的正確用法。 觸發關鍵詞:async, await, tokio, async-std, Future, spawn, channel, mpsc, select, runtime, blocking, async trait, stream, executor

Installationen
1
GitHub Stars
0
Aktualisiert
29. März
luckyegg168
Community

rust-crate-selection

Rust crate 選擇指南技能。按功能領域推薦經過實戰驗證的 crate: HTTP(reqwest/hyper/axum)、序列化(serde/serdejson/toml)、 CLI(clap/dialoguer/indicatif)、日誌(tracing/log/envlogger)、 加密(ring/rustls/argon2)、資料庫(sqlx/diesel/sea-orm)、 GUI(egui/iced/tauri)、測試(proptest/mockall/criterion)、 非同步(tokio/async-trait/futures)。 含選擇判斷標準、版本鎖定策略、Cargo.toml features 管理。 觸發關鍵詞:Rust crate, which crate, recommend crate, crate comparison, best Rust library, cargo dependency, version pinning, blessed.rs, lib.rs, crates.io, feature flags

Installationen
1
GitHub Stars
0
Aktualisiert
29. März
luckyegg168
Community

rust-ffi-interop

Rust FFI 互操作技能。涵蓋 PyO3 0.23 Rust ↔ Python 互操作、 cbindgen 生成 C header、bindgen 綁定 C 函式庫、extern "C" ABI、 [repr(C)] 記憶體佈局、CString/CStr 安全轉換、 null pointer 處理、panic boundary(catchunwind)、 記憶體所有權跨語言邊界管理、WASM 目標編譯。 觸發關鍵詞:FFI, PyO3, cbindgen, bindgen, extern C, repr C, CString, C interop, Python binding, WASM, foreign function, shared library, cdylib, staticlib

Installationen
1
GitHub Stars
0
Aktualisiert
29. März