策略模式
问题
Rust 中如何实现策略模式?
答案
Rust 有两种实现方式:trait 对象(动态分发)和闭包(函数式风格)。
方式 1:Trait(推荐)
trait Compressor {
fn compress(&self, data: &[u8]) -> Vec<u8>;
fn name(&self) -> &str;
}
struct Gzip;
struct Zstd;
impl Compressor for Gzip {
fn compress(&self, data: &[u8]) -> Vec<u8> {
// gzip 压缩逻辑
data.to_vec()
}
fn name(&self) -> &str { "gzip" }
}
impl Compressor for Zstd {
fn compress(&self, data: &[u8]) -> Vec<u8> {
// zstd 压缩逻辑
data.to_vec()
}
fn name(&self) -> &str { "zstd" }
}
// 静态分发(编译时确定策略)
fn process<C: Compressor>(compressor: &C, data: &[u8]) -> Vec<u8> {
compressor.compress(data)
}
// 动态分发(运行时选择策略)
fn process_dynamic(compressor: &dyn Compressor, data: &[u8]) -> Vec<u8> {
println!("使用 {} 压缩", compressor.name());
compressor.compress(data)
}
方式 2:闭包(简单场景)
fn sort_users(users: &mut Vec<User>, strategy: impl Fn(&User, &User) -> std::cmp::Ordering) {
users.sort_by(strategy);
}
// 使用
sort_users(&mut users, |a, b| a.name.cmp(&b.name)); // 按名字
sort_users(&mut users, |a, b| b.age.cmp(&a.age)); // 按年龄降序
trait vs 闭包选择
| 维度 | Trait | 闭包 |
|---|---|---|
| 状态 | 可以有字段 | 捕获环境 |
| 多个方法 | ✅ | ❌(通常单方法) |
| 可命名 | ✅ | ❌ |
| 复杂策略 | 推荐 | 不推荐 |
常见面试问题
Q1: Rust 的策略模式和 Java/Go 有什么不同?
答案:
Rust 独特之处在于可以选择静态分发(零成本)或动态分发:
- 泛型
<C: Compressor>→ 编译时确定,零开销 - Trait Object
&dyn Compressor→ 运行时确定,有 vtable 开销
Java/Go 只有动态分发(接口方法都是虚调用)。