How to use
- Copy the installation command and review the source package before installing it in your own agent environment.
- Check the source document for required tools, credentials and supported hosts.
- Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/luckyegg168/rust-skill --skill rust-design-patternsBefore you start
- Installation does not include a model subscription, API allowance or permission to access your files.
- Repository stars and installation counts describe activity, not an independent quality or security test.
Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.
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
- 零成本:編譯後與原始型別完全相同的記憶體佈局
// 基本定義
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 存取。
impl From<f64> for Meters {
fn from(v: f64) -> Self { Meters(v) }
}
// 自動獲得 Into<Meters> for f642. Builder Pattern(基礎)
適用於有多個可選欄位的 struct:
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) 在編譯期追蹤狀態:
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 保證離開作用域時自動執行清理:
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 | 是 | 僅初始化一次 | 全域單例 |
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 版本(動態分派,適合插件架構):
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 版本(無堆積配置,效能更佳):
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:
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:
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
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
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 reference | Builder 方法用 &mut self 但嘗試消耗 self | 改用 self(owned)作為 builder 方法接收者 |
unused type parameter H | Typestate 泛型參數未被實際欄位使用 | 新增 PhantomData<H> 欄位 |
trait objects cannot have associated functions | trait 內含 fn new() -> Self 等方法,無法做 dyn Trait | 加上 where Self: Sized 或移至 companion function |
cannot return reference to temporary value | RAII guard 的 Deref 回傳了臨時值的參考 | 確保 guard 內部持有擁有權的資料,Deref 回傳其參考 |
the trait bound Send is not satisfied | 將 Rc<RefCell<T>> 用於多執行緒 | 改用 Arc<Mutex<T>> |
Cargo.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,此為向後相容)參考來源
- Rust Design Patterns Book — 社群維護的模式集
- The Rust Book — Ch.17 OOP Features — trait objects 與動態分派
- Rust API Guidelines — Type Safety — Newtype 與型別安全
- Cliffle — Typestate Pattern — Typestate 深入教學
- Rust Reference — Drop — RAII 與 Drop 語意
- derive_more 文件 — 自動 derive 工具
- typed-builder 文件 — 型別安全 Builder derive


