Rust 之行为型模式详解

深入理解Rust对象行为协作与算法封装的艺术:策略、观察者、状态、命令、责任链、模板方法与访问者

Posted by Vlor on June 7, 2026

概述

行为型设计模式(Behavioral Patterns)是软件工程中专注于对象间职责分配与算法封装的核心方法论,其核心价值在于通过灵活的交互机制解耦对象行为,提升系统的可扩展性与可维护性。在Rust语言环境下,这一模式体系被赋予了独特的技术内涵——通过trait抽象、闭包捕获、枚举状态机与零成本泛型,行为型模式不仅保留了传统设计模式的解耦能力,更实现了编译期类型安全与运行时性能的完美平衡。

Rust行为型模式的核心优势:相较于传统面向对象语言中依赖继承导致的脆弱基类问题(如Java的策略类层次膨胀)和运行时多态开销(如C++的虚函数表查找),Rust通过trait组合实现行为复用,结合枚举与模式匹配处理状态流转,利用闭包与函数指针实现轻量级策略注入,从根本上重构了对象行为协作的表达边界。

本文聚焦七种经典行为型模式在Rust中的实现与演化:策略模式通过trait或函数指针实现算法替换;观察者模式利用回调闭包与通道实现事件驱动;状态模式借助枚举与模式匹配构建类型安全状态机;命令模式通过trait封装请求实现撤销/重做;责任链模式利用Option链式调用实现请求过滤;模板方法模式通过trait默认方法定义算法骨架;访问者模式结合双重分发实现操作与数据结构解耦。这些模式共同构成了Rust生态下行为协作的完整解决方案,为复杂业务逻辑开发提供了兼顾灵活性与安全性的工程实践范式。

核心概念

什么是行为型模式?

  • 策略模式:定义一系列算法,封装每个算法并使它们可互换,让算法的变化独立于使用它的客户
  • 观察者模式:定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖者都会收到通知
  • 状态模式:允许对象在内部状态改变时改变其行为,对象看起来像是修改了它的类
  • 命令模式:将请求封装为对象,从而支持参数化、队列化、日志化请求,以及可撤销操作
  • 责任链模式:使多个对象都有机会处理请求,从而避免请求发送者与接收者之间的耦合
  • 模板方法模式:定义算法骨架,将具体步骤延迟到子类实现,复用不变部分
  • 访问者模式:在不修改数据结构的前提下,定义作用于元素的新操作

为什么需要行为型模式?

Rust的组合优先原则与类型系统默认提供了强大的行为抽象能力,但在某些复杂场景中,直接实现会导致代码耦合或扩展困难:

  1. 算法替换需求:需要在运行时动态切换业务逻辑而不修改调用方
  2. 事件驱动架构:需要实现松耦合的发布-订阅机制支持异步通知
  3. 状态机管理:需要类型安全地表达复杂状态流转,避免非法状态组合
  4. 请求封装需求:需要将操作参数化、队列化,支持事务/撤销/日志
  5. 处理流程编排:需要灵活组合多个处理器,支持动态过滤与短路
  6. 算法骨架复用:需要定义通用流程,允许子类定制特定步骤
  7. 操作与数据解耦:需要为稳定数据结构添加新操作而不修改源码

策略模式详解

定义与作用

策略模式(Strategy Pattern)是一种行为型设计模式,其核心定义是”定义一系列算法,封装每个算法并使它们可互换,让算法的变化独立于使用它的客户”。在Rust语境下,这一模式通过trait抽象、函数指针与闭包三种方式实现,分别适用于不同场景的类型安全与性能需求。

// 方式1: Trait抽象(适合复杂策略)
pub trait SortStrategy {
    fn sort(&self, data: &mut [i32]);
}

pub struct QuickSort;
impl SortStrategy for QuickSort {
    fn sort(&self, data: &mut [i32]) {
        // 快速排序实现
        data.sort(); // 简化
    }
}

pub struct Context {
    strategy: Box<dyn SortStrategy>,
}

impl Context {
    pub fn new(strategy: Box<dyn SortStrategy>) -> Self {
        Context { strategy }
    }
    
    pub fn execute(&mut self, data: &mut [i32]) {
        self.strategy.sort(data);
    }
}

Rust策略模式的三种实现方式

1. Trait对象策略(动态分发)

适合策略逻辑复杂、需要运行时切换的场景:

pub trait PaymentStrategy {
    fn pay(&self, amount: f64) -> Result<String, PaymentError>;
}

pub struct PaymentContext {
    strategy: Box<dyn PaymentStrategy>,
}

impl PaymentContext {
    pub fn set_strategy(&mut self, strategy: Box<dyn PaymentStrategy>) {
        self.strategy = strategy;
    }
}

优势:运行时灵活切换,支持插件扩展 劣势:动态分发有~1-2纳秒开销,需要堆分配

2. 泛型策略(静态分发)

适合策略固定、追求零开销的场景:

pub trait SortStrategy {
    fn sort(data: &mut [i32]);
}

pub struct Context<S: SortStrategy> {
    _phantom: std::marker::PhantomData<S>,
}

impl<S: SortStrategy> Context<S> {
    pub fn execute(data: &mut [i32]) {
        S::sort(data);
    }
}

优势:编译期确定类型,零运行时开销,可内联优化 劣势:策略需在编译期确定,灵活性较低

3. 函数指针/闭包策略(轻量级)

适合简单策略、追求极简实现的场景:

pub type FilterFn = fn(&i32) -> bool;

pub struct DataProcessor {
    filter: FilterFn,
}

impl DataProcessor {
    pub fn new(filter: FilterFn) -> Self {
        DataProcessor { filter }
    }
    
    pub fn process(&self, data: &[i32]) -> Vec<i32> {
        data.iter().filter(|&x| (self.filter)(x)).copied().collect()
    }
}

// 使用闭包
let processor = DataProcessor::new(|x| x > 0);

优势:实现极简,无额外类型定义,闭包可捕获环境变量 劣势:复杂策略难以管理,类型信息较弱

代码示例

电商折扣策略系统

// ========== 策略trait定义 ==========
pub trait DiscountStrategy {
    fn calculate(&self, original_price: f64) -> f64;
    fn description(&self) -> &str;
}

// ========== 具体策略实现 ==========
pub struct NoDiscount;
impl DiscountStrategy for NoDiscount {
    fn calculate(&self, price: f64) -> f64 { price }
    fn description(&self) -> &str { "无折扣" }
}

pub struct PercentageDiscount {
    pub percent: f64, // 0.0 ~ 1.0
}
impl DiscountStrategy for PercentageDiscount {
    fn calculate(&self, price: f64) -> f64 {
        price * (1.0 - self.percent)
    }
    fn description(&self) -> &str { "百分比折扣" }
}

pub struct FixedDiscount {
    pub amount: f64,
}
impl DiscountStrategy for FixedDiscount {
    fn calculate(&self, price: f64) -> f64 {
        (price - self.amount).max(0.0)
    }
    fn description(&self) -> &str { "固定金额折扣" }
}

pub struct VIPDiscount;
impl DiscountStrategy for VIPDiscount {
    fn calculate(&self, price: f64) -> f64 {
        // VIP:满100减20,再打9折
        if price >= 100.0 {
            (price - 20.0) * 0.9
        } else {
            price * 0.95
        }
    }
    fn description(&self) -> &str { "VIP专享折扣" }
}

// ========== 上下文:订单 ==========
pub struct Order {
    pub items: Vec<OrderItem>,
    pub strategy: Box<dyn DiscountStrategy>,
}

pub struct OrderItem {
    pub name: String,
    pub price: f64,
    pub quantity: u32,
}

impl Order {
    pub fn new(strategy: Box<dyn DiscountStrategy>) -> Self {
        Order {
            items: Vec::new(),
            strategy,
        }
    }
    
    pub fn add_item(&mut self, item: OrderItem) {
        self.items.push(item);
    }
    
    pub fn total(&self) -> f64 {
        let original: f64 = self.items.iter()
            .map(|item| item.price * item.quantity as f64)
            .sum();
        self.strategy.calculate(original)
    }
    
    pub fn set_strategy(&mut self, strategy: Box<dyn DiscountStrategy>) {
        self.strategy = strategy;
    }
}

// ========== 使用示例 ==========
fn main() {
    let mut order = Order::new(Box::new(NoDiscount));
    
    order.add_item(OrderItem {
        name: "Rust Book".to_string(),
        price: 89.0,
        quantity: 2,
    });
    
    println!("原价: ¥{:.2}", order.total());
    
    // 运行时切换策略
    order.set_strategy(Box::new(PercentageDiscount { percent: 0.1 }));
    println!("9折后: ¥{:.2}", order.total());
    
    order.set_strategy(Box::new(VIPDiscount));
    println!("VIP价: ¥{:.2}", order.total());
    println!("策略: {}", order.strategy.description());
}

应用场景

  • 支付渠道选择:支付宝/微信/信用卡等支付策略动态切换
  • 数据压缩算法:gzip/zstd/brotli等压缩策略按需选择
  • 缓存淘汰策略:LRU/LFU/TTL等策略配置化
  • 日志输出格式:JSON/Plain/Structured等格式策略

Rust优势:通过trait对象支持运行时策略切换,通过泛型支持编译期零开销策略,通过闭包实现轻量级策略注入,满足不同场景的性能与灵活性需求。

观察者模式详解

定义与作用

观察者模式(Observer Pattern)是一种行为型设计模式,其核心定义是”定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖者都会自动收到通知并更新”。在Rust语境下,这一模式通过回调闭包、通道(Channel)与trait对象实现,分别适用于同步通知、异步事件流与多态订阅场景。

// 方式1: 闭包回调(简单同步)
pub struct Subject {
    observers: Vec<Box<dyn Fn(&str)>>,
}

impl Subject {
    pub fn subscribe<F>(&mut self, callback: F)
    where F: Fn(&str) + 'static {
        self.observers.push(Box::new(callback));
    }
    
    pub fn notify(&self, message: &str) {
        for observer in &self.observers {
            observer(message);
        }
    }
}

Rust观察者模式的三种实现方式

1. 闭包回调(同步通知)

适合简单场景、同步执行、无并发需求:

pub trait Observer {
    fn update(&self, event: &Event);
}

pub struct Subject {
    observers: Vec<Box<dyn Observer>>,
}

优势:实现简单,类型安全,易于调试 劣势:同步阻塞,不适合耗时操作

2. 通道+线程(异步事件流)

适合跨线程通知、异步处理、高并发场景:

use std::sync::mpsc::{channel, Sender};

pub struct EventBus {
    senders: Vec<Sender<Event>>,
}

impl EventBus {
    pub fn subscribe(&mut self) -> Receiver<Event> {
        let (tx, rx) = channel();
        self.senders.push(tx);
        rx
    }
    
    pub fn publish(&self, event: Event) {
        for tx in &self.senders {
            let _ = tx.send(event.clone());
        }
    }
}

优势:支持跨线程异步通知,解耦生产消费 劣势:需要处理通道错误,内存开销略高

3. Arc+Mutex共享状态(多线程安全)

适合需要共享状态、多线程读写场景:

use std::sync::{Arc, Mutex};

pub struct SharedState {
    observers: Arc<Mutex<Vec<Box<dyn Fn(&State) + Send>>>>,
}

impl SharedState {
    pub fn notify(&self, state: &State) {
        let observers = self.observers.lock().unwrap();
        for observer in observers.iter() {
            observer(state);
        }
    }
}

优势:线程安全,状态共享灵活 劣势:锁竞争可能影响性能

代码示例

股票价格通知系统

use std::sync::{Arc, Mutex};
use std::collections::HashMap;

// ========== 事件定义 ==========
#[derive(Clone, Debug)]
pub struct StockEvent {
    pub symbol: String,
    pub price: f64,
    pub change: f64,
    pub timestamp: u64,
}

// ========== 观察者trait ==========
pub trait StockObserver: Send {
    fn on_price_update(&self, event: &StockEvent);
    fn id(&self) -> &str;
}

// ========== 具体观察者实现 ==========
pub struct EmailNotifier {
    pub id: String,
    pub email: String,
}

impl StockObserver for EmailNotifier {
    fn on_price_update(&self, event: &StockEvent) {
        println!("[Email] To: {} | {} price: ${:.2} ({:+.2}%)", 
                 self.email, event.symbol, event.price, event.change);
    }
    fn id(&self) -> &str { &self.id }
}

pub struct SMSNotifier {
    pub id: String,
    pub phone: String,
}

impl StockObserver for SMSNotifier {
    fn on_price_update(&self, event: &StockEvent) {
        println!("[SMS] To: {} | {} ${:.2}", 
                 self.phone, event.symbol, event.price);
    }
    fn id(&self) -> &str { &self.id }
}

pub struct Dashboard {
    pub id: String,
    pub prices: Mutex<HashMap<String, f64>>,
}

impl StockObserver for Dashboard {
    fn on_price_update(&self, event: &StockEvent) {
        let mut prices = self.prices.lock().unwrap();
        prices.insert(event.symbol.clone(), event.price);
        println!("[Dashboard] Updated {}: ${:.2}", event.symbol, event.price);
    }
    fn id(&self) -> &str { &self.id }
}

// ========== 主题:股票行情 ==========
pub struct StockTicker {
    pub symbol: String,
    observers: Vec<Box<dyn StockObserver>>,
}

impl StockTicker {
    pub fn new(symbol: &str) -> Self {
        StockTicker {
            symbol: symbol.to_string(),
            observers: Vec::new(),
        }
    }
    
    pub fn attach(&mut self, observer: Box<dyn StockObserver>) {
        self.observers.push(observer);
    }
    
    pub fn detach(&mut self, observer_id: &str) {
        self.observers.retain(|obs| obs.id() != observer_id);
    }
    
    pub fn update_price(&self, price: f64, change: f64) {
        let event = StockEvent {
            symbol: self.symbol.clone(),
            price,
            change,
            timestamp: std::time::SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .unwrap()
                .as_secs(),
        };
        
        for observer in &self.observers {
            observer.on_price_update(&event);
        }
    }
}

// ========== 使用示例 ==========
fn main() {
    let mut aapl = StockTicker::new("AAPL");
    
    // 订阅者
    aapl.attach(Box::new(EmailNotifier {
        id: "email1".to_string(),
        email: "user@example.com".to_string(),
    }));
    
    aapl.attach(Box::new(SMSNotifier {
        id: "sms1".to_string(),
        phone: "+86-138-0000-0000".to_string(),
    }));
    
    let dashboard = Arc::new(Dashboard {
        id: "dash1".to_string(),
        prices: Mutex::new(HashMap::new()),
    });
    
    aapl.attach(Box::new(Arc::clone(&dashboard) as Box<dyn StockObserver>));
    
    // 价格更新触发通知
    aapl.update_price(178.5, 2.3);
    aapl.update_price(180.2, 0.95);
    
    // 取消订阅
    aapl.detach("sms1");
    aapl.update_price(179.8, -0.22);
}

应用场景

  • GUI事件系统:按钮点击、窗口大小变化等事件通知
  • 微服务事件总线:服务间通过事件解耦通信
  • 实时数据推送:股票/物联网/游戏状态同步
  • 配置热更新:配置变更自动通知相关模块

Rust优势:通过trait对象支持多态观察者,通过通道实现跨线程异步通知,通过Arc+Mutex确保多线程安全,结合所有权系统避免观察者生命周期问题。

状态模式详解

定义与作用

状态模式(State Pattern)是一种行为型设计模式,其核心定义是”允许对象在内部状态改变时改变其行为,对象看起来像是修改了它的类”。在Rust语境下,这一模式通过枚举状态机、trait对象状态与类型状态模式三种方式实现,分别适用于不同复杂度与类型安全需求。

// 方式1: 枚举+模式匹配(推荐)
pub enum OrderState {
    Created,
    Paid,
    Shipped,
    Delivered,
    Cancelled,
}

pub struct Order {
    pub id: u64,
    pub state: OrderState,
}

impl Order {
    pub fn pay(&mut self) -> Result<(), String> {
        match self.state {
            OrderState::Created => {
                self.state = OrderState::Paid;
                Ok(())
            }
            _ => Err("Only created orders can be paid".into()),
        }
    }
}

Rust状态模式的三种实现方式

1. 枚举状态机(类型安全+零开销)

适合状态固定、转换逻辑清晰的场景:

pub enum ConnectionState {
    Disconnected,
    Connecting { retry: u32 },
    Connected { session_id: String },
}

impl ConnectionState {
    fn can_send(&self) -> bool {
        matches!(self, ConnectionState::Connected { .. })
    }
}

优势:编译期检查状态合法性,无运行时开销,模式匹配清晰 劣势:新增状态需修改枚举定义

2. Trait对象状态(运行时多态)

适合状态行为复杂、需要动态扩展的场景:

pub trait State {
    fn handle(&self, ctx: &mut Context, event: Event);
    fn name(&self) -> &str;
}

pub struct Context {
    state: Box<dyn State>,
}

优势:支持运行时状态切换,行为封装灵活 劣势:动态分发开销,类型信息部分丢失

3. 类型状态模式(编译期状态验证)

适合对状态流转有严格约束的场景:

// 状态标记类型
pub struct Created;
pub struct Paid;
pub struct Shipped;

// 泛型订单,状态由类型参数约束
pub struct Order<S> {
    pub id: u64,
    _state: std::marker::PhantomData<S>,
}

impl Order<Created> {
    pub fn pay(self) -> Order<Paid> {
        Order { id: self.id, _state: PhantomData }
    }
}

impl Order<Paid> {
    pub fn ship(self) -> Order<Shipped> {
        Order { id: self.id, _state: PhantomData }
    }
}

优势:编译期确保状态流转合法,零运行时开销 劣势:实现复杂,类型签名冗长

代码示例

订单生命周期状态机

// ========== 状态定义 ==========
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum OrderState {
    Created,
    Paid,
    Processing,
    Shipped,
    Delivered,
    Cancelled,
    Refunded,
}

impl OrderState {
    // 状态转换规则
    pub fn can_transition_to(self, next: OrderState) -> bool {
        use OrderState::*;
        matches!(
            (self, next),
            (Created, Paid | Cancelled) |
            (Paid, Processing | Cancelled | Refunded) |
            (Processing, Shipped | Cancelled) |
            (Shipped, Delivered | Cancelled) |
            (Delivered, Refunded)
        )
    }
    
    pub fn is_terminal(self) -> bool {
        matches!(self, Delivered | Cancelled | Refunded)
    }
}

// ========== 订单实体 ==========
#[derive(Debug)]
pub struct Order {
    pub id: u64,
    pub state: OrderState,
    pub history: Vec<(OrderState, u64)>, // 状态变更日志
}

impl Order {
    pub fn new(id: u64) -> Self {
        Order {
            id,
            state: OrderState::Created,
            history: vec![(OrderState::Created, now())],
        }
    }
    
    pub fn transition(&mut self, next: OrderState) -> Result<(), String> {
        if !self.state.can_transition_to(next) {
            return Err(format!(
                "Invalid transition: {:?} -> {:?}", 
                self.state, next
            ));
        }
        
        if self.state.is_terminal() {
            return Err("Cannot transition from terminal state".into());
        }
        
        self.history.push((next, now()));
        self.state = next;
        Ok(())
    }
    
    pub fn pay(&mut self) -> Result<(), String> {
        self.transition(OrderState::Paid)
    }
    
    pub fn ship(&mut self) -> Result<(), String> {
        self.transition(OrderState::Shipped)
    }
    
    pub fn deliver(&mut self) -> Result<(), String> {
        self.transition(OrderState::Delivered)
    }
    
    pub fn cancel(&mut self) -> Result<(), String> {
        self.transition(OrderState::Cancelled)
    }
    
    pub fn refund(&mut self) -> Result<(), String> {
        self.transition(OrderState::Refunded)
    }
}

fn now() -> u64 {
    std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap()
        .as_secs()
}

// ========== 使用示例 ==========
fn main() {
    let mut order = Order::new(1001);
    
    println!("Order #{} created: {:?}", order.id, order.state);
    
    // 正常流程
    order.pay().unwrap();
    println!("Paid: {:?}", order.state);
    
    order.ship().unwrap();
    println!("Shipped: {:?}", order.state);
    
    order.deliver().unwrap();
    println!("Delivered: {:?}", order.state);
    
    // 非法操作:已送达的订单不能取消
    assert!(order.cancel().is_err());
    
    // 状态历史
    println!("\nState history:");
    for (state, ts) in &order.history {
        println!("  {:?} @ {}", state, ts);
    }
}

应用场景

  • 工作流引擎:审批流程、订单流程等状态驱动业务
  • 网络协议实现:TCP连接状态机、HTTP请求生命周期
  • UI组件状态:按钮启用/禁用、表单验证状态
  • 游戏角色状态:站立/移动/攻击/死亡等状态切换

Rust优势:通过枚举+模式匹配实现类型安全的状态转换,编译期捕获非法状态组合;通过类型状态模式可实现零开销的编译期状态验证;结合Result类型优雅处理状态转换错误。

命令模式详解

定义与作用

命令模式(Command Pattern)是一种行为型设计模式,其核心定义是”将请求封装为对象,从而支持参数化、队列化、日志化请求,以及可撤销操作”。在Rust语境下,这一模式通过trait封装、枚举命令与闭包命令三种方式实现,分别适用于复杂命令、固定命令集与轻量级操作场景。

// 方式1: Trait封装(适合复杂命令)
pub trait Command {
    fn execute(&mut self) -> Result<(), String>;
    fn undo(&mut self) -> Result<(), String>;
    fn name(&self) -> &str;
}

pub struct TextEditor {
    pub content: String,
}

pub struct InsertText {
    editor: *mut TextEditor, // 注意:实际应使用更安全的引用方式
    text: String,
    position: usize,
}

impl Command for InsertText {
    fn execute(&mut self) -> Result<(), String> {
        unsafe {
            (*self.editor).content.insert_str(self.position, &self.text);
        }
        Ok(())
    }
    
    fn undo(&mut self) -> Result<(), String> {
        unsafe {
            let end = self.position + self.text.len();
            (*self.editor).content.replace_range(self.position..end, "");
        }
        Ok(())
    }
    
    fn name(&self) -> &str { "InsertText" }
}

Rust命令模式的三种实现方式

1. Trait对象命令(支持撤销/重做)

适合需要记录历史、支持事务的复杂场景:

pub trait Command: Any {
    fn execute(&mut self) -> Result<(), Error>;
    fn undo(&mut self) -> Result<(), Error>;
}

pub struct CommandHistory {
    history: Vec<Box<dyn Command>>,
}

优势:支持撤销/重做,命令可序列化,易于测试 劣势:需要手动管理生命周期,动态分发有开销

2. 枚举命令(类型安全+零开销)

适合命令集固定、追求性能的场景:

pub enum EditorCommand {
    Insert { text: String, pos: usize },
    Delete { range: Range<usize> },
    Format { style: Style },
}

impl EditorCommand {
    fn execute(&self, editor: &mut Editor) -> Result<(), Error> {
        match self {
            EditorCommand::Insert { text, pos } => {
                editor.content.insert_str(*pos, text);
                Ok(())
            }
            // ... 其他分支
        }
    }
}

优势:编译期类型检查,无虚表开销,模式匹配清晰 劣势:新增命令需修改枚举,扩展性略低

3. 闭包命令(轻量级)

适合简单操作、无需撤销的场景:

pub type SimpleCommand = Box<dyn FnOnce() -> Result<(), Error> + Send>;

pub struct TaskQueue {
    tasks: Vec<SimpleCommand>,
}

impl TaskQueue {
    pub fn push<F>(&mut self, task: F)
    where F: FnOnce() -> Result<(), Error> + Send + 'static {
        self.tasks.push(Box::new(task));
    }
    
    pub fn execute_all(&mut self) -> Result<(), Error> {
        for task in self.tasks.drain(..) {
            task()?;
        }
        Ok(())
    }
}

优势:实现极简,闭包可捕获环境变量,无额外类型定义 劣势:不支持撤销,类型信息弱,调试困难

代码示例

文本编辑器命令系统(支持撤销)

use std::any::Any;

// ========== 命令trait ==========
pub trait Command: Any {
    fn execute(&mut self) -> Result<(), String>;
    fn undo(&mut self) -> Result<(), String>;
    fn name(&self) -> &str;
}

// ========== 编辑器状态 ==========
#[derive(Clone, Debug)]
pub struct EditorState {
    pub content: String,
    pub cursor: usize,
}

pub struct TextEditor {
    pub state: EditorState,
    pub history: Vec<Box<dyn Command>>,
    pub redo_stack: Vec<Box<dyn Command>>,
}

impl TextEditor {
    pub fn new() -> Self {
        TextEditor {
            state: EditorState {
                content: String::new(),
                cursor: 0,
            },
            history: Vec::new(),
            redo_stack: Vec::new(),
        }
    }
    
    pub fn execute(&mut self, mut cmd: Box<dyn Command>) -> Result<(), String> {
        cmd.execute()?;
        self.redo_stack.clear(); // 执行新命令,清空重做栈
        self.history.push(cmd);
        Ok(())
    }
    
    pub fn undo(&mut self) -> Result<(), String> {
        if let Some(mut cmd) = self.history.pop() {
            cmd.undo()?;
            self.redo_stack.push(cmd);
            Ok(())
        } else {
            Err("Nothing to undo".into())
        }
    }
    
    pub fn redo(&mut self) -> Result<(), String> {
        if let Some(mut cmd) = self.redo_stack.pop() {
            cmd.execute()?;
            self.history.push(cmd);
            Ok(())
        } else {
            Err("Nothing to redo".into())
        }
    }
}

// ========== 具体命令:插入文本 ==========
pub struct InsertText {
    text: String,
    position: usize,
    // 保存执行前的状态用于撤销
    snapshot: Option<String>,
}

impl InsertText {
    pub fn new(text: String, position: usize) -> Self {
        InsertText {
            text,
            position,
            snapshot: None,
        }
    }
}

impl Command for InsertText {
    fn execute(&mut self) -> Result<(), String> {
        // 实际执行时需要访问编辑器,这里简化处理
        // 真实场景应通过引用或回调传递编辑器
        println!("Insert '{}' at {}", self.text, self.position);
        Ok(())
    }
    
    fn undo(&mut self) -> Result<(), String> {
        println!("Undo insert at {}", self.position);
        Ok(())
    }
    
    fn name(&self) -> &str { "InsertText" }
}

// ========== 具体命令:删除文本 ==========
pub struct DeleteText {
    start: usize,
    end: usize,
    deleted: Option<String>,
}

impl DeleteText {
    pub fn new(start: usize, end: usize) -> Self {
        DeleteText {
            start,
            end,
            deleted: None,
        }
    }
}

impl Command for DeleteText {
    fn execute(&mut self) -> Result<(), String> {
        println!("Delete [{}..{})", self.start, self.end);
        Ok(())
    }
    
    fn undo(&mut self) -> Result<(), String> {
        println!("Restore deleted text");
        Ok(())
    }
    
    fn name(&self) -> &str { "DeleteText" }
}

// ========== 使用示例 ==========
fn main() {
    let mut editor = TextEditor::new();
    
    // 执行命令
    editor.execute(Box::new(InsertText::new("Hello, ".to_string(), 0)))?;
    editor.execute(Box::new(InsertText::new("Rust!".to_string(), 7)))?;
    
    println!("Content: {:?}", editor.state.content);
    
    // 撤销
    editor.undo()?;
    println!("After undo: {:?}", editor.state.content);
    
    // 重做
    editor.redo()?;
    println!("After redo: {:?}", editor.state.content);
    
    Ok::<(), String>(())
}

应用场景

  • 编辑器操作:插入/删除/格式化等支持撤销的操作
  • 事务系统:数据库操作的提交/回滚
  • 宏录制:记录用户操作序列并回放
  • 任务队列:异步任务的封装与调度

Rust优势:通过trait对象支持命令的多态与撤销,通过枚举实现类型安全的命令集,通过闭包实现轻量级任务封装;结合Result类型优雅处理命令执行错误。

责任链模式详解

定义与作用

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,其核心定义是”使多个对象都有机会处理请求,从而避免请求发送者与接收者之间的耦合,请求沿着链传递直到被处理”。在Rust语境下,这一模式通过Option链式调用、trait对象链与枚举处理器三种方式实现,分别适用于不同复杂度与类型安全需求。

// 方式1: Option链式调用(函数式风格)
pub type HandlerFn = fn(Request) -> Option<Response>;

pub struct Chain {
    handlers: Vec<HandlerFn>,
}

impl Chain {
    pub fn new(handlers: Vec<HandlerFn>) -> Self {
        Chain { handlers }
    }
    
    pub fn handle(&self, request: Request) -> Option<Response> {
        for handler in &self.handlers {
            if let Some(response) = handler(request) {
                return Some(response);
            }
        }
        None
    }
}

Rust责任链模式的三种实现方式

1. Option链式调用(函数式风格)

适合处理逻辑简单、追求简洁表达的场景:

pub fn handle_request(req: Request) -> Option<Response> {
    validate_auth(&req)
        .or_else(|| parse_payload(&req))
        .or_else(|| route_request(&req))
        .or_else(|| fallback_handler(&req))
}

优势:代码简洁,利用Option的组合语义,短路求值 劣势:难以动态配置处理器顺序,调试信息有限

2. Trait对象链(运行时配置)

适合处理器动态加载、顺序可配置的场景:

pub trait Handler {
    fn handle(&self, ctx: &mut Context) -> HandleResult;
    fn set_next(&mut self, next: Box<dyn Handler>);
}

pub struct Chain {
    head: Option<Box<dyn Handler>>,
}

优势:运行时动态组装处理链,支持插件扩展 劣势:动态分发开销,生命周期管理复杂

3. 枚举处理器(编译期类型安全)

适合处理器集合固定、追求零开销的场景:

pub enum Handler {
    Auth(AuthHandler),
    Parse(ParseHandler),
    Route(RouteHandler),
}

impl Handler {
    fn handle(&self, ctx: &mut Context) -> HandleResult {
        match self {
            Handler::Auth(h) => h.handle(ctx),
            Handler::Parse(h) => h.handle(ctx),
            Handler::Route(h) => h.handle(ctx),
        }
    }
}

优势:编译期类型检查,无虚表开销,模式匹配清晰 劣势:新增处理器需修改枚举,扩展性略低

代码示例

HTTP请求处理管道

// ========== 请求/响应定义 ==========
#[derive(Debug, Clone)]
pub struct Request {
    pub path: String,
    pub method: String,
    pub headers: std::collections::HashMap<String, String>,
    pub body: Option<String>,
}

#[derive(Debug, Clone)]
pub struct Response {
    pub status: u16,
    pub headers: std::collections::HashMap<String, String>,
    pub body: Option<String>,
}

#[derive(Debug)]
pub enum HandleResult {
    Continue(Request),
    Respond(Response),
    Error(String),
}

// ========== 处理器trait ==========
pub trait Handler: Send + Sync {
    fn handle(&self, req: Request) -> HandleResult;
    fn name(&self) -> &str;
}

// ========== 具体处理器:认证 ==========
pub struct AuthHandler {
    pub required_token: Option<String>,
}

impl Handler for AuthHandler {
    fn handle(&self, req: Request) -> HandleResult {
        if let Some(required) = &self.required_token {
            match req.headers.get("Authorization") {
                Some(token) if token == required => {
                    println!("[Auth] ✓ Passed");
                    HandleResult::Continue(req)
                }
                _ => {
                    println!("[Auth] ✗ Failed");
                    HandleResult::Respond(Response {
                        status: 401,
                        headers: [("WWW-Authenticate".into(), "Bearer".into())]
                            .into_iter().collect(),
                        body: Some("Unauthorized".into()),
                    })
                }
            }
        } else {
            HandleResult::Continue(req)
        }
    }
    
    fn name(&self) -> &str { "AuthHandler" }
}

// ========== 具体处理器:日志 ==========
pub struct LoggingHandler {
    pub prefix: String,
}

impl Handler for LoggingHandler {
    fn handle(&self, req: Request) -> HandleResult {
        println!("[{}] {} {}", self.prefix, req.method, req.path);
        HandleResult::Continue(req)
    }
    
    fn name(&self) -> &str { "LoggingHandler" }
}

// ========== 具体处理器:路由 ==========
pub struct RouteHandler {
    pub routes: std::collections::HashMap<String, fn(Request) -> Response>,
}

impl Handler for RouteHandler {
    fn handle(&self, req: Request) -> HandleResult {
        if let Some(handler) = self.routes.get(&req.path) {
            println!("[Route] Matched {}", req.path);
            HandleResult::Respond(handler(req))
        } else {
            HandleResult::Respond(Response {
                status: 404,
                headers: std::collections::HashMap::new(),
                body: Some("Not Found".into()),
            })
        }
    }
    
    fn name(&self) -> &str { "RouteHandler" }
}

// ========== 责任链执行器 ==========
pub struct Pipeline {
    handlers: Vec<Box<dyn Handler>>,
}

impl Pipeline {
    pub fn new() -> Self {
        Pipeline { handlers: Vec::new() }
    }
    
    pub fn add<H: Handler + 'static>(&mut self, handler: H) -> &mut Self {
        self.handlers.push(Box::new(handler));
        self
    }
    
    pub fn handle(&self, req: Request) -> Response {
        let mut current_req = req;
        
        for handler in &self.handlers {
            println!("[Pipeline] Processing: {}", handler.name());
            match handler.handle(current_req) {
                HandleResult::Continue(req) => current_req = req,
                HandleResult::Respond(resp) => return resp,
                HandleResult::Error(msg) => {
                    return Response {
                        status: 500,
                        headers: std::collections::HashMap::new(),
                        body: Some(format!("Internal error: {}", msg)),
                    };
                }
            }
        }
        
        // 默认响应
        Response {
            status: 200,
            headers: std::collections::HashMap::new(),
            body: Some("OK".into()),
        }
    }
}

// ========== 使用示例 ==========
fn main() {
    let mut pipeline = Pipeline::new();
    
    // 组装处理链:日志 → 认证 → 路由
    pipeline
        .add(LoggingHandler { prefix: "API".into() })
        .add(AuthHandler { 
            required_token: Some("secret-token".into()) 
        })
        .add(RouteHandler {
            routes: [
                ("/hello".into(), |req| Response {
                    status: 200,
                    headers: std::collections::HashMap::new(),
                    body: Some(format!("Hello from {}", req.path)),
                }),
            ].into_iter().collect(),
        });
    
    // 请求1: 无认证头 → 401
    let req1 = Request {
        path: "/hello".into(),
        method: "GET".into(),
        headers: std::collections::HashMap::new(),
        body: None,
    };
    let resp1 = pipeline.handle(req1);
    println!("Response 1: {}\n", resp1.status);
    
    // 请求2: 有认证头 → 200
    let req2 = Request {
        path: "/hello".into(),
        method: "GET".into(),
        headers: [("Authorization".into(), "secret-token".into())]
            .into_iter().collect(),
        body: None,
    };
    let resp2 = pipeline.handle(req2);
    println!("Response 2: {} - {:?}", resp2.status, resp2.body);
}

应用场景

  • Web中间件:认证、日志、限流、CORS等请求处理链
  • 数据验证管道:格式校验→业务校验→持久化校验
  • 事件过滤器:日志级别过滤、敏感词过滤、权限过滤
  • 插件系统:动态加载处理器实现功能扩展

Rust优势:通过trait对象支持运行时动态组装处理链,通过Option组合实现函数式短路求值,通过枚举实现编译期类型安全的处理器集合;结合Result类型优雅处理链式错误传播。

模板方法模式详解

定义与作用

模板方法模式(Template Method Pattern)是一种行为型设计模式,其核心定义是”定义算法骨架,将具体步骤延迟到子类实现,复用不变部分”。在Rust语境下,这一模式通过trait默认方法、泛型约束与闭包注入三种方式实现,分别适用于不同灵活性与类型安全需求。

// 方式1: Trait默认方法(推荐)
pub trait DataProcessor {
    // 模板方法:定义算法骨架
    fn process(&self, input: &str) -> String {
        let validated = self.validate(input);
        let transformed = self.transform(validated);
        self.format(transformed)
    }
    
    // 钩子方法:子类可选重写
    fn validate(&self, input: &str) -> &str {
        input.trim()
    }
    
    // 抽象方法:子类必须实现
    fn transform(&self, input: &str) -> String;
    fn format(&self, input: String) -> String;
}

pub struct UpperCaseProcessor;
impl DataProcessor for UpperCaseProcessor {
    fn transform(&self, input: &str) -> String {
        input.to_uppercase()
    }
    fn format(&self, input: String) -> String {
        format!("[UPPER] {}", input)
    }
}

Rust模板方法模式的三种实现方式

1. Trait默认方法(标准实现)

适合算法骨架固定、步骤可定制的场景:

pub trait Pipeline {
    fn execute(&self, data: Input) -> Output {
        let pre = self.pre_process(data);
        let core = self.core_logic(pre);
        self.post_process(core)
    }
    
    fn pre_process(&self, data: Input) -> Input { data }
    fn core_logic(&self, data: Input) -> Output;
    fn post_process(&self, output: Output) -> Output { output }
}

优势:代码复用清晰,子类只需实现必要步骤,默认方法提供扩展点 劣势:子类可能意外覆盖关键步骤,需文档约束

2. 泛型约束(编译期多态)

适合追求零开销、步骤类型固定的场景:

pub struct Algorithm<P: PreProcess, C: CoreLogic, Po: PostProcess> {
    _phantom: PhantomData<(P, C, Po)>,
}

impl<P, C, Po> Algorithm<P, C, Po>
where
    P: PreProcess,
    C: CoreLogic,
    Po: PostProcess,
{
    pub fn execute(input: Input) -> Output {
        let pre = P::process(input);
        let core = C::process(pre);
        Po::process(core)
    }
}

优势:编译期确定类型,零运行时开销,类型安全 劣势:类型签名复杂,泛型爆炸可能增加编译时间

3. 闭包注入(轻量级定制)

适合简单定制、追求极简实现的场景:

pub struct ConfigurableProcessor {
    pre: Box<dyn Fn(&str) -> String>,
    core: Box<dyn Fn(String) -> String>,
    post: Box<dyn Fn(String) -> String>,
}

impl ConfigurableProcessor {
    pub fn new<F1, F2, F3>(pre: F1, core: F2, post: F3) -> Self
    where
        F1: Fn(&str) -> String + 'static,
        F2: Fn(String) -> String + 'static,
        F3: Fn(String) -> String + 'static,
    {
        ConfigurableProcessor {
            pre: Box::new(pre),
            core: Box::new(core),
            post: Box::new(post),
        }
    }
    
    pub fn process(&self, input: &str) -> String {
        let pre = (self.pre)(input);
        let core = (self.core)(pre);
        (self.post)(core)
    }
}

优势:实现极简,闭包可捕获环境变量,运行时灵活配置 劣势:类型信息弱,调试困难,动态分发有开销

代码示例

数据导入管道模板

// ========== 模板trait ==========
pub trait ImportPipeline {
    // 模板方法:定义导入流程骨架
    fn import(&self, source: &str) -> Result<ImportResult, ImportError> {
        println!("[Pipeline] Starting import from: {}", source);
        
        // 步骤1: 连接数据源(可定制)
        let connection = self.connect(source)?;
        
        // 步骤2: 读取数据(可定制)
        let raw = self.read(&connection)?;
        
        // 步骤3: 验证数据(钩子方法,可选)
        let validated = self.validate(raw)?;
        
        // 步骤4: 转换数据(必须实现)
        let transformed = self.transform(validated)?;
        
        // 步骤5: 持久化(可定制)
        let result = self.persist(transformed)?;
        
        // 步骤6: 清理(钩子方法,可选)
        self.cleanup(&connection)?;
        
        println!("[Pipeline] Import completed");
        Ok(result)
    }
    
    // 抽象方法:子类必须实现
    fn transform(&self, data: RawData) -> Result<TransformedData, ImportError>;
    
    // 默认实现:子类可选重写
    fn connect(&self, source: &str) -> Result<Connection, ImportError> {
        println!("[Default] Connecting to: {}", source);
        Ok(Connection { id: 1 })
    }
    
    fn read(&self, conn: &Connection) -> Result<RawData, ImportError> {
        println!("[Default] Reading data");
        Ok(RawData { rows: vec![] })
    }
    
    fn validate(&self, data: RawData) -> Result<RawData, ImportError> {
        println!("[Default] Validation passed");
        Ok(data)
    }
    
    fn persist(&self, data: TransformedData) -> Result<ImportResult, ImportError> {
        println!("[Default] Persisting {} records", data.records.len());
        Ok(ImportResult { count: data.records.len() })
    }
    
    fn cleanup(&self, _conn: &Connection) -> Result<(), ImportError> {
        println!("[Default] Cleanup completed");
        Ok(())
    }
}

// ========== 辅助类型 ==========
#[derive(Debug)]
pub struct Connection { pub id: u64 }
#[derive(Debug)]
pub struct RawData { pub rows: Vec<String> }
#[derive(Debug)]
pub struct TransformedData { pub records: Vec<Record> }
#[derive(Debug)]
pub struct Record { pub fields: std::collections::HashMap<String, String> }
#[derive(Debug)]
pub struct ImportResult { pub count: usize }
#[derive(Debug)]
pub enum ImportError {
    ConnectionFailed(String),
    ReadError(String),
    ValidationError(String),
    TransformError(String),
}

// ========== 具体实现:CSV导入 ==========
pub struct CsvImportPipeline {
    pub delimiter: char,
    pub has_header: bool,
}

impl ImportPipeline for CsvImportPipeline {
    fn transform(&self, data: RawData) -> Result<TransformedData, ImportError> {
        println!("[CSV] Transforming with delimiter '{}'", self.delimiter);
        
        let records = data.rows.iter().map(|row| {
            let fields: Vec<&str> = row.split(self.delimiter).collect();
            let mut map = std::collections::HashMap::new();
            for (i, field) in fields.iter().enumerate() {
                map.insert(format!("col_{}", i), field.to_string());
            }
            Record { fields: map }
        }).collect();
        
        Ok(TransformedData { records })
    }
    
    // 重写验证步骤:检查CSV格式
    fn validate(&self, data: RawData) -> Result<RawData, ImportError> {
        for (i, row) in data.rows.iter().enumerate() {
            if row.matches(self.delimiter).count() < 2 {
                return Err(ImportError::ValidationError(
                    format!("Row {} has insufficient columns", i)
                ));
            }
        }
        println!("[CSV] Validation passed: {} rows", data.rows.len());
        Ok(data)
    }
}

// ========== 具体实现:JSON导入 ==========
pub struct JsonImportPipeline;

impl ImportPipeline for JsonImportPipeline {
    fn transform(&self, data: RawData) -> Result<TransformedData, ImportError> {
        println!("[JSON] Parsing JSON data");
        
        // 简化:实际应使用serde_json
        let records = data.rows.iter().map(|row| {
            Record {
                fields: [("raw".into(), row.clone())].into_iter().collect(),
            }
        }).collect();
        
        Ok(TransformedData { records })
    }
    
    // 重写连接步骤:模拟HTTP连接
    fn connect(&self, source: &str) -> Result<Connection, ImportError> {
        if !source.starts_with("http") {
            return Err(ImportError::ConnectionFailed(
                "JSON source must be HTTP URL".into()
            ));
        }
        println!("[JSON] HTTP connection established");
        Ok(Connection { id: 2 })
    }
}

// ========== 使用示例 ==========
fn main() -> Result<(), ImportError> {
    // CSV导入
    let csv_pipeline = CsvImportPipeline {
        delimiter: ',',
        has_header: true,
    };
    
    let csv_result = csv_pipeline.import("data/users.csv")?;
    println!("CSV import: {} records\n", csv_result.count);
    
    // JSON导入
    let json_pipeline = JsonImportPipeline;
    let json_result = json_pipeline.import("https://api.example.com/users")?;
    println!("JSON import: {} records", json_result.count);
    
    Ok(())
}

应用场景

  • 数据导入导出:不同格式(CSV/JSON/XML)的导入流程复用
  • 测试框架:setup→test→teardown的测试生命周期
  • 构建系统:编译→链接→打包的构建流程定制
  • 工作流引擎:审批→执行→通知的流程模板

Rust优势:通过trait默认方法实现算法骨架复用,子类只需关注差异化步骤;通过泛型约束实现编译期零开销的模板实例化;结合Result类型优雅处理各步骤的错误传播。

访问者模式详解

定义与作用

访问者模式(Visitor Pattern)是一种行为型设计模式,其核心定义是”在不修改数据结构的前提下,定义作用于元素的新操作,将操作与对象结构解耦”。在Rust语境下,这一模式通过双重分发、枚举匹配与泛型访问者三种方式实现,分别适用于不同复杂度与类型安全需求。

// 方式1: 双重分发(经典实现)
pub trait Element {
    fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result;
}

pub trait Visitor {
    type Result;
    fn visit_concrete_a(&mut self, element: &ConcreteA) -> Self::Result;
    fn visit_concrete_b(&mut self, element: &ConcreteB) -> Self::Result;
}

pub struct ConcreteA { pub value: i32 }
impl Element for ConcreteA {
    fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result {
        visitor.visit_concrete_a(self)
    }
}

pub struct ConcreteB { pub text: String }
impl Element for ConcreteB {
    fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result {
        visitor.visit_concrete_b(self)
    }
}

Rust访问者模式的三种实现方式

1. 双重分发Trait(标准实现)

适合元素类型固定、操作需要多态的场景:

pub trait Shape {
    fn accept<V: ShapeVisitor>(&self, visitor: &mut V) -> V::Output;
}

pub trait ShapeVisitor {
    type Output;
    fn visit_circle(&mut self, c: &Circle) -> Self::Output;
    fn visit_rect(&mut self, r: &Rectangle) -> Self::Output;
}

优势:操作与数据结构完全解耦,新增操作无需修改元素 劣势:新增元素类型需修改所有访问者,双重分发有性能开销

2. 枚举+模式匹配(简化实现)

适合元素集合固定、追求简洁的场景:

pub enum Shape {
    Circle { radius: f64 },
    Rectangle { width: f64, height: f64 },
}

impl Shape {
    pub fn area(&self) -> f64 {
        match self {
            Shape::Circle { radius } => std::f64::consts::PI * radius * radius,
            Shape::Rectangle { width, height } => width * height,
        }
    }
}

优势:实现简洁,编译期类型检查,无虚表开销 劣势:新增操作需修改枚举匹配,操作与数据耦合

3. 泛型访问者(编译期多态)

适合追求零开销、访问者类型固定的场景:

pub trait Element {
    fn accept<V>(&self, visitor: &mut V) -> V::Result 
    where V: Visitor<Self>;
}

pub trait Visitor<E> {
    type Result;
    fn visit(&mut self, element: &E) -> Self::Result;
}

优势:编译期确定类型,零运行时开销,类型安全 劣势:泛型代码膨胀,类型签名复杂

代码示例

AST表达式求值访问者

// ========== 元素trait ==========
pub trait Expr: std::fmt::Debug {
    fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result;
}

// ========== 访问者trait ==========
pub trait Visitor {
    type Result;
    fn visit_literal(&mut self, lit: &Literal) -> Self::Result;
    fn visit_binary(&mut self, bin: &BinaryExpr) -> Self::Result;
    fn visit_unary(&mut self, unary: &UnaryExpr) -> Self::Result;
}

// ========== 具体元素:字面量 ==========
#[derive(Debug)]
pub struct Literal {
    pub value: f64,
}

impl Expr for Literal {
    fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result {
        visitor.visit_literal(self)
    }
}

// ========== 具体元素:二元表达式 ==========
#[derive(Debug)]
pub enum BinaryOp { Add, Sub, Mul, Div }

#[derive(Debug)]
pub struct BinaryExpr {
    pub op: BinaryOp,
    pub left: Box<dyn Expr>,
    pub right: Box<dyn Expr>,
}

impl Expr for BinaryExpr {
    fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result {
        visitor.visit_binary(self)
    }
}

// ========== 具体元素:一元表达式 ==========
#[derive(Debug)]
pub enum UnaryOp { Neg, Abs }

#[derive(Debug)]
pub struct UnaryExpr {
    pub op: UnaryOp,
    pub operand: Box<dyn Expr>,
}

impl Expr for UnaryExpr {
    fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result {
        visitor.visit_unary(self)
    }
}

// ========== 访问者实现1: 求值 ==========
pub struct EvalVisitor;

impl Visitor for EvalVisitor {
    type Result = Result<f64, String>;
    
    fn visit_literal(&mut self, lit: &Literal) -> Self::Result {
        Ok(lit.value)
    }
    
    fn visit_binary(&mut self, bin: &BinaryExpr) -> Self::Result {
        let left = bin.left.accept(self)?;
        let right = bin.right.accept(self)?;
        
        match bin.op {
            BinaryOp::Add => Ok(left + right),
            BinaryOp::Sub => Ok(left - right),
            BinaryOp::Mul => Ok(left * right),
            BinaryOp::Div => {
                if right == 0.0 {
                    Err("Division by zero".into())
                } else {
                    Ok(left / right)
                }
            }
        }
    }
    
    fn visit_unary(&mut self, unary: &UnaryExpr) -> Self::Result {
        let operand = unary.operand.accept(self)?;
        match unary.op {
            UnaryOp::Neg => Ok(-operand),
            UnaryOp::Abs => Ok(operand.abs()),
        }
    }
}

// ========== 访问者实现2: 打印 ==========
pub struct PrintVisitor {
    pub output: String,
}

impl Visitor for PrintVisitor {
    type Result = ();
    
    fn visit_literal(&mut self, lit: &Literal) {
        self.output.push_str(&format!("{}", lit.value));
    }
    
    fn visit_binary(&mut self, bin: &BinaryExpr) {
        self.output.push('(');
        bin.left.accept(self);
        let op = match bin.op {
            BinaryOp::Add => '+',
            BinaryOp::Sub => '-',
            BinaryOp::Mul => '*',
            BinaryOp::Div => '/',
        };
        self.output.push(op);
        bin.right.accept(self);
        self.output.push(')');
    }
    
    fn visit_unary(&mut self, unary: &UnaryExpr) {
        let prefix = match unary.op {
            UnaryOp::Neg => "-",
            UnaryOp::Abs => "abs(",
        };
        self.output.push_str(prefix);
        unary.operand.accept(self);
        if matches!(unary.op, UnaryOp::Abs) {
            self.output.push(')');
        }
    }
}

// ========== 使用示例 ==========
fn main() -> Result<(), String> {
    // 构建表达式: (3 + 4) * 2
    let expr: Box<dyn Expr> = Box::new(BinaryExpr {
        op: BinaryOp::Mul,
        left: Box::new(BinaryExpr {
            op: BinaryOp::Add,
            left: Box::new(Literal { value: 3.0 }),
            right: Box::new(Literal { value: 4.0 }),
        }),
        right: Box::new(Literal { value: 2.0 }),
    });
    
    // 求值
    let mut eval = EvalVisitor;
    let result = expr.accept(&mut eval)?;
    println!("Result: {}", result); // 14.0
    
    // 打印
    let mut print = PrintVisitor { output: String::new() };
    expr.accept(&mut print);
    println!("Expression: {}", print.output); // ((3+4)*2)
    
    Ok(())
}

应用场景

  • 编译器/解释器:AST遍历实现类型检查、代码生成、优化
  • 文档处理:对不同节点类型执行渲染、导出、统计等操作
  • 配置校验:对配置树执行验证、转换、序列化等操作
  • UI框架:对组件树执行布局计算、事件分发、渲染等操作

性能对比: | 实现方式 | 新增元素开销 | 新增操作开销 | 运行时开销 | |———-|————-|————-|———–| | 双重分发 | 高(修改所有Visitor) | 低(新增Visitor) | 虚表调用×2 | | 枚举匹配 | 低(修改enum) | 高(修改所有match) | 无 | | 泛型访问者 | 中(泛型实例化) | 低(新增类型) | 无(内联) |

Rust优势:通过trait系统实现类型安全的双重分发,编译期确保访问者方法完整性;通过枚举+模式匹配提供简化替代方案;结合Result类型优雅处理访问过程中的错误。

实践应用

综合案例:工作流引擎

本案例设计为”可配置工作流引擎”,通过整合策略、状态、命令、责任链、模板方法五种行为型模式,构建灵活可靠的任务执行系统。系统架构中:

  • 状态模式:TaskState管理任务生命周期(待执行→执行中→完成/失败)
  • 策略模式:RetryStrategy实现不同重试策略(固定间隔/指数退避/不重试)
  • 命令模式:TaskCommand封装任务执行逻辑,支持撤销与日志
  • 责任链模式:MiddlewareChain实现任务预处理(鉴权→限流→日志)
  • 模板方法模式:WorkflowTemplate定义工作流执行骨架,支持自定义步骤

协作流程:

  1. 客户端提交任务,责任链执行预处理中间件
  2. 模板方法定义任务执行流程:准备→执行→清理
  3. 状态机确保任务状态合法流转
  4. 策略模式决定失败后的重试行为
  5. 命令模式记录执行历史,支持回滚

各模式协同解决了任务调度、错误处理、流程定制、可观测性等复杂需求。

核心实现(简化版)

use std::sync::Arc;
use std::time::{Duration, Instant};

// ========== 状态模式:任务状态 ==========
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TaskState {
    Pending,
    Running,
    Completed,
    Failed { retries: u32 },
}

impl TaskState {
    pub fn can_transition_to(self, next: TaskState) -> bool {
        use TaskState::*;
        matches!(
            (self, next),
            (Pending, Running) |
            (Running, Completed | Failed { .. }) |
            (Failed { retries: r }, Pending) if r < 3
        )
    }
}

// ========== 策略模式:重试策略 ==========
pub trait RetryStrategy: Send + Sync {
    fn should_retry(&self, attempt: u32, error: &str) -> bool;
    fn delay(&self, attempt: u32) -> Duration;
}

pub struct NoRetry;
impl RetryStrategy for NoRetry {
    fn should_retry(&self, _attempt: u32, _error: &str) -> bool { false }
    fn delay(&self, _attempt: u32) -> Duration { Duration::ZERO }
}

pub struct ExponentialBackoff {
    pub base: Duration,
    pub max_delay: Duration,
}
impl RetryStrategy for ExponentialBackoff {
    fn should_retry(&self, attempt: u32, _error: &str) -> bool {
        attempt < 3
    }
    fn delay(&self, attempt: u32) -> Duration {
        let delay = self.base * (2u32.pow(attempt));
        delay.min(self.max_delay)
    }
}

// ========== 命令模式:任务命令 ==========
pub trait TaskCommand: Send {
    fn execute(&mut self) -> Result<TaskResult, TaskError>;
    fn name(&self) -> &str;
}

pub struct TaskResult {
    pub output: String,
    pub duration: Duration,
}

pub struct TaskError {
    pub message: String,
    pub retryable: bool,
}

// 示例命令:模拟任务
pub struct SimulateTask {
    pub name: String,
    pub should_fail: bool,
    pub attempt: u32,
}

impl TaskCommand for SimulateTask {
    fn execute(&mut self) -> Result<TaskResult, TaskError> {
        println!("[Task] Executing: {} (attempt {})", self.name, self.attempt);
        
        if self.should_fail && self.attempt < 2 {
            return Err(TaskError {
                message: "Simulated failure".into(),
                retryable: true,
            });
        }
        
        std::thread::sleep(Duration::from_millis(100));
        
        Ok(TaskResult {
            output: format!("{} completed", self.name),
            duration: Duration::from_millis(100),
        })
    }
    
    fn name(&self) -> &str { &self.name }
}

// ========== 责任链模式:中间件 ==========
pub trait Middleware: Send + Sync {
    fn handle(&self, ctx: &mut TaskContext) -> Result<(), String>;
}

pub struct AuthMiddleware {
    pub required_role: Option<String>,
}
impl Middleware for AuthMiddleware {
    fn handle(&self, ctx: &mut TaskContext) -> Result<(), String> {
        if let Some(role) = &self.required_role {
            if ctx.user_role.as_ref() != Some(role) {
                return Err("Unauthorized".into());
            }
        }
        Ok(())
    }
}

pub struct LoggingMiddleware;
impl Middleware for LoggingMiddleware {
    fn handle(&self, ctx: &mut TaskContext) -> Result<(), String> {
        println!("[Middleware] Task: {} by user: {:?}", 
                 ctx.task_name, ctx.user_id);
        Ok(())
    }
}

pub struct RateLimitMiddleware {
    pub max_per_minute: u32,
    pub current: std::sync::atomic::AtomicU32,
}
impl Middleware for RateLimitMiddleware {
    fn handle(&self, _ctx: &mut TaskContext) -> Result<(), String> {
        // 简化:实际应实现滑动窗口限流
        Ok(())
    }
}

pub struct TaskContext {
    pub task_name: String,
    pub user_id: Option<u64>,
    pub user_role: Option<String>,
    pub metadata: std::collections::HashMap<String, String>,
}

// ========== 模板方法:工作流执行 ==========
pub trait WorkflowTemplate: Send {
    // 模板方法:定义执行骨架
    fn run(&self, ctx: &mut TaskContext) -> Result<TaskResult, TaskError> {
        self.before_execute(ctx)?;
        
        let result = self.execute_core(ctx)?;
        
        self.after_execute(ctx, &result)?;
        
        Ok(result)
    }
    
    // 钩子方法:子类可选重写
    fn before_execute(&self, _ctx: &mut TaskContext) -> Result<(), TaskError> {
        Ok(())
    }
    
    fn after_execute(&self, _ctx: &mut TaskContext, _result: &TaskResult) 
        -> Result<(), TaskError> { Ok(()) }
    
    // 抽象方法:子类必须实现
    fn execute_core(&self, ctx: &mut TaskContext) -> Result<TaskResult, TaskError>;
}

// ========== 具体工作流:带重试的任务执行 ==========
pub struct RetryableWorkflow {
    pub command: Box<dyn TaskCommand>,
    pub retry_strategy: Box<dyn RetryStrategy>,
    pub middlewares: Vec<Arc<dyn Middleware>>,
}

impl WorkflowTemplate for RetryableWorkflow {
    fn execute_core(&self, ctx: &mut TaskContext) -> Result<TaskResult, TaskError> {
        // 执行中间件链
        for mw in &self.middlewares {
            mw.handle(ctx).map_err(|e| TaskError {
                message: format!("Middleware failed: {}", e),
                retryable: false,
            })?;
        }
        
        // 执行命令
        self.command.execute()
    }
    
    fn after_execute(&self, ctx: &mut TaskContext, result: &TaskResult) 
        -> Result<(), TaskError> 
    {
        println!("[Workflow] Task completed in {:?}", result.duration);
        Ok(())
    }
}

// ========== 任务执行器 ==========
pub struct TaskExecutor {
    pub state: TaskState,
    pub workflow: Box<dyn WorkflowTemplate>,
    pub retry_count: u32,
}

impl TaskExecutor {
    pub fn new(workflow: Box<dyn WorkflowTemplate>) -> Self {
        TaskExecutor {
            state: TaskState::Pending,
            workflow,
            retry_count: 0,
        }
    }
    
    pub fn execute(&mut self, ctx: &mut TaskContext) -> Result<TaskResult, TaskError> {
        // 状态检查
        if !self.state.can_transition_to(TaskState::Running) {
            return Err(TaskError {
                message: format!("Invalid state transition: {:?}", self.state),
                retryable: false,
            });
        }
        self.state = TaskState::Running;
        
        // 执行工作流
        match self.workflow.run(ctx) {
            Ok(result) => {
                self.state = TaskState::Completed;
                Ok(result)
            }
            Err(error) => {
                let strategy = &self.workflow; // 实际应获取策略
                if error.retryable && self.retry_strategy_should_retry() {
                    self.retry_count += 1;
                    self.state = TaskState::Failed { retries: self.retry_count };
                    // 实际应实现延迟重试
                    Err(TaskError {
                        message: format!("Will retry (attempt {})", self.retry_count),
                        retryable: true,
                    })
                } else {
                    self.state = TaskState::Failed { retries: self.retry_count };
                    Err(error)
                }
            }
        }
    }
    
    fn retry_strategy_should_retry(&self) -> bool {
        // 简化:实际应委托给策略对象
        self.retry_count < 3
    }
}

// ========== 使用示例 ==========
fn main() -> Result<(), TaskError> {
    // 构建工作流
    let workflow = Box::new(RetryableWorkflow {
        command: Box::new(SimulateTask {
            name: "DataSync".into(),
            should_fail: true,
            attempt: 1,
        }),
        retry_strategy: Box::new(ExponentialBackoff {
            base: Duration::from_secs(1),
            max_delay: Duration::from_secs(10),
        }),
        middlewares: vec![
            Arc::new(AuthMiddleware { required_role: Some("admin".into()) }),
            Arc::new(LoggingMiddleware),
        ],
    });
    
    let mut executor = TaskExecutor::new(workflow);
    
    let mut ctx = TaskContext {
        task_name: "DataSync".into(),
        user_id: Some(1001),
        user_role: Some("admin".into()),
        metadata: std::collections::HashMap::new(),
    };
    
    // 执行任务(可能重试)
    match executor.execute(&mut ctx) {
        Ok(result) => println!("✓ Success: {}", result.output),
        Err(e) => println!("✗ Failed: {} (retryable: {})", e.message, e.retryable),
    }
    
    println!("Final state: {:?}", executor.state);
    
    Ok(())
}

模式协作优势:

  • 状态模式确保任务生命周期合法流转,避免非法状态组合
  • 策略模式灵活配置重试行为,支持不同业务场景的容错需求
  • 命令模式封装任务逻辑,支持执行历史追踪与回滚
  • 责任链模式解耦预处理逻辑,便于动态组合鉴权/限流/日志等中间件
  • 模板方法模式复用执行骨架,子类只需关注核心业务逻辑

常见错误与解决

错误1:策略模式 - 生命周期管理不当

错误表现:策略对象持有引用时未正确处理生命周期,导致悬垂引用。

错误代码:

pub struct PaymentContext<'a> {
    strategy: &'a dyn PaymentStrategy, // 生命周期绑定
}

fn problematic() {
    let ctx;
    {
        let strat = PercentageDiscount { percent: 0.1 };
        ctx = PaymentContext { strategy: &strat }; // strat即将被丢弃
    } // strat在此处被drop
    ctx.calculate(100.0); // ❌ 悬垂引用!
}

解决方案:使用Box或Arc转移所有权确保生命周期安全。

修正代码:

pub struct PaymentContext {
    strategy: Box<dyn PaymentStrategy>, // 拥有所有权
}

// 或共享所有权
pub struct PaymentContext {
    strategy: Arc<dyn PaymentStrategy>,
}

错误2:观察者模式 - 迭代时修改集合

错误表现:通知观察者时修改观察者列表,导致迭代器失效。

错误代码:

impl Subject {
    fn notify(&mut self, event: &Event) {
        for observer in &self.observers {
            observer.update(event);
            // ❌ 可能在update中调用detach,修改self.observers
        }
    }
}

解决方案:先收集需要移除的观察者,迭代完成后再统一处理。

修正代码:

impl Subject {
    fn notify(&mut self, event: &Event) {
        // 先收集需要移除的观察者ID
        let to_remove: Vec<String> = self.observers.iter()
            .filter(|obs| obs.should_remove_after_notify(event))
            .map(|obs| obs.id().to_string())
            .collect();
        
        // 通知所有观察者
        for observer in &self.observers {
            observer.update(event);
        }
        
        // 最后统一移除
        for id in to_remove {
            self.observers.retain(|obs| obs.id() != id);
        }
    }
}

错误3:状态模式 - 非法状态转换

错误表现:未验证状态转换合法性,导致业务逻辑错误。

错误代码:

impl Order {
    fn ship(&mut self) {
        // ❌ 未检查当前状态,已取消的订单也能发货
        self.state = OrderState::Shipped;
    }
}

解决方案:在状态转换方法中验证前置状态。

修正代码:

impl Order {
    fn ship(&mut self) -> Result<(), String> {
        match self.state {
            OrderState::Paid | OrderState::Processing => {
                self.state = OrderState::Shipped;
                Ok(())
            }
            _ => Err(format!(
                "Cannot ship order in state: {:?}", 
                self.state
            )),
        }
    }
}

错误4:命令模式 - 撤销状态不一致

错误表现:命令执行后未保存足够信息,导致撤销失败。

错误代码:

pub struct DeleteText {
    range: Range<usize>,
    // ❌ 未保存被删除的内容
}

impl Command for DeleteText {
    fn undo(&mut self) -> Result<(), String> {
        // ❌ 无法恢复已删除的文本
        Err("Cannot undo: original content lost".into())
    }
}

解决方案:命令执行前保存必要状态用于撤销。

修正代码:

pub struct DeleteText {
    range: Range<usize>,
    deleted_content: Option<String>, // 执行后填充
}

impl Command for DeleteText {
    fn execute(&mut self, editor: &mut Editor) -> Result<(), String> {
        self.deleted_content = Some(
            editor.content[self.range.clone()].to_string()
        );
        editor.content.replace_range(self.range.clone(), "");
        Ok(())
    }
    
    fn undo(&mut self, editor: &mut Editor) -> Result<(), String> {
        if let Some(content) = &self.deleted_content {
            editor.content.insert_str(self.range.start, content);
            Ok(())
        } else {
            Err("Cannot undo: no content to restore".into())
        }
    }
}

错误5:访问者模式 - 忘记实现访问方法

错误表现:新增元素类型后,忘记在访问者中实现对应方法,导致编译错误或运行时恐慌。

错误代码:

// 新增元素类型
pub struct Triangle { /* ... */ }
impl Element for Triangle {
    fn accept<V: Visitor>(&self, visitor: &mut V) -> V::Result {
        // ❌ Visitor trait没有visit_triangle方法
        // 编译错误!
    }
}

解决方案:使用宏或代码生成确保访问者方法完整性。

修正代码:

// 方案1: 使用macro_rules!生成访问者代码
macro_rules! define_visitor {
    ($($elem:ident => $method:ident),*) => {
        pub trait Visitor {
            type Result;
            $(fn $method(&mut self, e: &$elem) -> Self::Result;)*
        }
        
        $(impl Element for $elem {
            fn accept<V: Visitor>(&self, v: &mut V) -> V::Result {
                v.$method(self)
            }
        })*
    };
}

// 使用宏定义所有元素和访问方法
define_visitor! {
    Literal => visit_literal,
    BinaryExpr => visit_binary,
    UnaryExpr => visit_unary,
    Triangle => visit_triangle  // 新增时只需在此添加
}

// 方案2: 使用enum+match替代双重分发(简化场景)
pub enum Expr {
    Literal(Literal),
    Binary(BinaryExpr),
    Triangle(Triangle), // 新增时修改此处
}

impl Expr {
    pub fn accept<V: ExprVisitor>(&self, v: &mut V) -> V::Result {
        match self {
            Expr::Literal(e) => v.visit_literal(e),
            Expr::Binary(e) => v.visit_binary(e),
            Expr::Triangle(e) => v.visit_triangle(e), // 新增分支
        }
    }
}

总结要点

Rust行为型模式的核心价值

  1. 组合优于继承:通过trait组合与闭包注入实现行为复用,避免继承层次僵化
  2. 零成本抽象:泛型与内联优化确保设计模式不引入运行时开销
  3. 编译期安全:类型系统提前捕获状态非法转换、访问者方法缺失等问题
  4. 并发友好:Send/Synctrait与Arc/Mutex原语简化线程安全的行为协作

模式选择指南

场景需求 推荐模式 Rust实现要点
算法动态替换 策略模式 trait对象 或 闭包 + 泛型
事件通知机制 观察者模式 回调闭包 或 通道+线程
状态机管理 状态模式 枚举+模式匹配 或 类型状态
请求封装/撤销 命令模式 trait封装 + 历史记录
处理流程编排 责任链模式 Option链式 或 trait对象链
算法骨架复用 模板方法 trait默认方法 + 钩子函数
操作与数据解耦 访问者模式 双重分发trait 或 枚举匹配

性能优化建议

  • 优先静态分发:能用泛型就不用trait对象,减少虚表调用开销
  • 避免过度抽象:简单场景直接使用函数/闭包,无需引入完整模式
  • 状态机优化:使用#[repr(u8)]枚举减少内存占用,模式匹配可被LLVM优化
  • 观察者批量通知:避免在通知循环中修改集合,先收集后处理

Rust惯用法融合

  1. 利用?操作符简化错误传播:各模式中的步骤方法统一返回Result
  2. 使用impl Trait简化返回类型:避免暴露具体策略/命令类型
  3. 结合derive宏减少样板代码:Clone/Debug/PartialEq等
  4. 采用PhantomData处理类型参数:类型状态模式中标记状态类型

进阶资源

Rust社区风采

https://example.com/rust-behavioral-patterns.jpg

Rust社区通过类型系统与创新抽象,为传统行为型设计模式注入了新的活力。在保持模式解耦与复用核心价值的同时,借助trait、枚举、闭包与零成本泛型等特性,实现了前所未有的类型安全与性能保障。这些实践不仅提升了代码质量,更为构建可靠、高效、可维护的大型系统提供了坚实的方法论基础。🦀✨