Learn Rust Coding · 课时

构建器模式

逐步构造对象。

第 1 / 4 课13 个步骤

构建器模式 是 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 构建器模式
  2. 新类型模式
  3. 类型状态构建器
  4. Deref 与包装器易用性
← 返回 Learn Rust Coding