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(回呼與事件系統)、…

ソースを見る

使い方

  1. インストールコマンドをコピーし、自分の環境へ導入する前にソースを確認します。
  2. 必要なツール、認証情報、対応環境を原文で確認します。
  3. 入力と成果物を指定し、出力を資料と照合します。
npx skills add https://github.com/luckyegg168/rust-skill --skill rust-design-patterns

開始前の確認

  • 導入にはモデル契約、API枠、ファイルへのアクセス許可は含まれません。
  • スター数や導入数は活動の指標であり、独立した品質・安全性試験ではありません。
リポジトリの原文

見出し、例、コード、表、リンク、参照画像を含む原文を表示しています。

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

タスクに関連する項目

同じリポジトリから

関連する Skills

すべての Skills
luckyegg168
コミュニティ

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

導入数
1
GitHub Stars
0
更新日
3月29日
luckyegg168
コミュニティ

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

導入数
1
GitHub Stars
0
更新日
3月29日
luckyegg168
コミュニティ

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

導入数
1
GitHub Stars
0
更新日
3月29日