Cómo usar
- Copia el comando y revisa el paquete antes de instalarlo en tu entorno de agente.
- Consulta las herramientas, credenciales y entornos necesarios en el documento original.
- Describe las entradas y el resultado deseado; contrasta la salida con las fuentes.
npx skills add https://github.com/luckyegg168/rust-skill --skill rust-design-patternsAntes de empezar
- La instalación no incluye suscripción al modelo, cuota API ni permisos sobre tus archivos.
- Las estrellas e instalaciones reflejan actividad, no una prueba independiente de calidad o seguridad.
Contenido del repositorio de origen con títulos, ejemplos, código, tablas, enlaces e imágenes preservados.
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


