建造者模式
问题
Rust 中建造者模式如何实现?
答案
建造者模式在 Rust 中非常常见,因为 Rust 没有函数重载和默认参数。
基础实现
struct Server {
host: String,
port: u16,
max_connections: usize,
timeout: std::time::Duration,
}
struct ServerBuilder {
host: String,
port: u16,
max_connections: usize,
timeout: std::time::Duration,
}
impl ServerBuilder {
fn new(host: impl Into<String>, port: u16) -> Self {
Self {
host: host.into(),
port,
max_connections: 100, // 默认值
timeout: std::time::Duration::from_secs(30),
}
}
fn max_connections(mut self, n: usize) -> Self {
self.max_connections = n;
self
}
fn timeout(mut self, d: std::time::Duration) -> Self {
self.timeout = d;
self
}
fn build(self) -> Server {
Server {
host: self.host,
port: self.port,
max_connections: self.max_connections,
timeout: self.timeout,
}
}
}
// 使用
let server = ServerBuilder::new("localhost", 8080)
.max_connections(200)
.timeout(std::time::Duration::from_secs(60))
.build();
类型状态 Builder(编译时安全)
确保必填字段不被遗漏:
use std::marker::PhantomData;
// 状态标记
struct NoHost;
struct HasHost;
struct NoPort;
struct HasPort;
struct RequestBuilder<H, P> {
host: Option<String>,
port: Option<u16>,
path: String,
_h: PhantomData<H>,
_p: PhantomData<P>,
}
impl RequestBuilder<NoHost, NoPort> {
fn new() -> Self {
Self {
host: None, port: None,
path: "/".into(),
_h: PhantomData, _p: PhantomData,
}
}
}
impl<P> RequestBuilder<NoHost, P> {
fn host(self, host: impl Into<String>) -> RequestBuilder<HasHost, P> {
RequestBuilder {
host: Some(host.into()), port: self.port,
path: self.path,
_h: PhantomData, _p: PhantomData,
}
}
}
impl<H> RequestBuilder<H, NoPort> {
fn port(self, port: u16) -> RequestBuilder<H, HasPort> {
RequestBuilder {
host: self.host, port: Some(port),
path: self.path,
_h: PhantomData, _p: PhantomData,
}
}
}
// 只有设置了 host 和 port 才能 build
impl RequestBuilder<HasHost, HasPort> {
fn build(self) -> String {
format!("{}:{}{}", self.host.unwrap(), self.port.unwrap(), self.path)
}
}
// 使用
let url = RequestBuilder::new()
.host("example.com")
.port(443)
.build(); // ✅
// RequestBuilder::new().build(); // ❌ 编译错误!
常见面试问题
Q1: Builder 模式和 Functional Options 模式如何选择?
答案:
| 特性 | Builder | Functional Options |
|---|---|---|
| Rust 中实现 | 结构体 + 方法链 | 闭包参数 |
| 类型安全 | 可用 Typestate 保证 | 较弱 |
| 可读性 | ✅ | ✅ |
| 推荐度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐(Go 中更常见) |
Rust 社区首选 Builder 模式。