构建器模式
逐步构造对象。
构建器模式 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。
为什么使用 Builder?
Rust 没有命名参数或可选参数。当一个结构体包含许多字段,尤其是可选字段时,带有八个位置参数的构造函数会难以阅读,也容易出错。
Builder 模式解决了这个问题。您可以通过带名称的方法逐步配置对象,最后调用 build() 生成值。这样的代码读起来就像一句流畅的句子。
目标结构体
先定义您实际想要构造的类型。这里的服务器配置包含一个必需的主机字段,以及几个可选设置。
请注意,这些字段是私有的,目的是鼓励通过 builder 进行构造,而不是直接使用结构体字面量。
pub struct ServerConfig {
host: String,
port: u16,
max_connections: usize,
use_tls: bool,
}单独的 Builder 类型
经典做法是使用第二个结构体,也就是 builder。它与目标类型对应,但保存构造过程中的状态。可选字段通常会变成 Option<T>,这样就能区分“未设置”和“明确设置”。
pub struct ServerConfigBuilder {
host: String,
port: Option<u16>,
max_connections: Option<usize>,
use_tls: bool,
}启动 Builder
为 builder 提供一个只接收必需字段的构造函数。所有可选字段一开始都设为 None 或默认值。
一种常见约定是在目标类型上提供一个 builder() 方法,并由它返回 builder。
impl ServerConfig {
pub fn builder(host: impl Into<String>) -> ServerConfigBuilder {
ServerConfigBuilder {
host: host.into(),
port: None,
max_connections: None,
use_tls: false,
}
}
}Setter 方法按值接收 self
每个 setter 都会消耗 self,修改一个字段,然后返回 self。返回拥有所有权的值后,就可以流畅地链式调用。
这种基于所有权的链式调用是符合 Rust 惯用风格的做法,也能避免生命周期方面的麻烦。
impl ServerConfigBuilder {
pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}
pub fn use_tls(mut self, yes: bool) -> Self {
self.use_tls = yes;
self
}
}在 build() 中应用默认值
末端的 build() 会将 builder 转换为真正的类型。您可以在这里使用 unwrap_or 为仍为 None 的内容填入默认值。
impl ServerConfigBuilder {
pub fn build(self) -> ServerConfig {
ServerConfig {
host: self.host,
port: self.port.unwrap_or(8080),
max_connections: self.max_connections.unwrap_or(128),
use_tls: self.use_tls,
}
}
}流畅构造
现在,构造过程从上到下清晰可读。必需数据传入 builder();每个可选设置都通过名称明确的方法调用完成。
跳过的字段会静默采用默认值。
fn main() {
let cfg = ServerConfig::builder("localhost")
.port(9000)
.use_tls(true)
.build();
println!("{}:{} tls={}", cfg.host, cfg.port, cfg.use_tls);
}完整的可运行示例
下面是一个可以运行的完整程序,其中将整个模式压缩在一起。它展示了跳过的字段如何在 build() 中回退到默认值。
struct Config { name: String, retries: u32 }
struct Builder { name: String, retries: Option<u32> }
impl Config {
fn builder(name: &str) -> Builder {
Builder { name: name.to_string(), retries: None }
}
}
impl Builder {
fn retries(mut self, n: u32) -> Self { self.retries = Some(n); self }
fn build(self) -> Config {
Config { name: self.name, retries: self.retries.unwrap_or(3) }
}
}
fn main() {
let c = Config::builder("job").build();
println!("{} retries={}", c.name, c.retries);
}使用 Result 处理可能失败的 build
有时配置可能无效,例如端口为零。可以让 build() 返回 Result,这样验证失败就会以可恢复的错误形式呈现,而不是触发 panic。
impl ServerConfigBuilder {
pub fn try_build(self) -> Result<ServerConfig, String> {
let port = self.port.unwrap_or(8080);
if port == 0 {
return Err("port must be non-zero".into());
}
Ok(ServerConfig { host: self.host, port,
max_connections: self.max_connections.unwrap_or(128),
use_tls: self.use_tls })
}
}derive_builder Crate
手动编写 builder 需要重复许多代码。derive_builder crate 可以根据注解生成完整的 builder。
您只需为字段添加默认值注解,就能免费获得生成的 FooBuilder,其中包含 setter 和可失败的 build()。
use derive_builder::Builder;
#[derive(Builder)]
struct Channel {
#[builder(default = "8080")]
port: u16,
name: String,
}拥有所有权的 Builder 与可变引用 Builder
有两种风格。拥有所有权的风格会消耗 self,可以自然地进行链式调用。&mut self 风格会返回 &mut Self,允许您将构造过程拆分到多个语句中,而无需重新绑定。
拥有所有权的风格更常用于一次性构造;可变引用风格适合在循环中进行条件配置。
impl ServerConfigBuilder {
pub fn port_ref(&mut self, port: u16) -> &mut Self {
self.port = Some(port);
self
}
}快速检查
检验您对拥有所有权的 self Builder 风格的理解。
回顾
Builder 模式弥补了 Rust 缺少可选参数的不足。Builder 类型保存构造过程中的状态,setter 会消耗并返回 self 以支持链式调用,而 build() 会应用默认值并生成最终值。
使用 build() 返回的 Result 进行验证,并在希望省去样板代码时使用 derive_builder。
用 AI 导师学习 Rust — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 39
- 课程
- 144
常见问题解答
「构建器模式」课时是免费的吗?
是的 — 「构建器模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。
「构建器模式」这节课中我会学到什么?
逐步构造对象。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「构建器模式」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。