Rust实现构建器模式和使用Bon库中的构建器

实现构建器模式的一种方式

这里参考资料2的文章,修改部分代码后如下。这段代码的目的是使用构建器模式创建和初始化Person对象。以下是各部分的解释:

  • 结构体定义

    • Person: 定义了一个结构体,包含name、age、address和sex四个字段。address和sex是可选的
    • PersonBuilder: 用于逐步构建Person对象的构建器结构体
  • 构建器实现

    • new: 创建一个新的PersonBuilder实例,初始化name和age,其他字段为None
    • with_address: 设置address字段,返回修改后的构建器
    • with_sex: 设置sex字段,返回修改后的构建器
    • build: 生成最终的Person对象
  • 主函数

    • 使用PersonBuilder构建一个Person对象,设置name、age、address和sex
    • 打印Person对象及其各个字段的值
  • 目的

    • 封装对象创建过程: 使用构建器模式来管理对象初始化的复杂性
    • 可选字段设置: 允许灵活地设置可选字段,而不必在创建对象时提供所有信息
    • 链式调用: 提供链式调用的接口,使代码更简洁易读
rust 复制代码
#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
    address: Option<String>,
    sex: Option<String>,
}

struct PersonBuilder {
    name: String,
    age: u32,
    address: Option<String>,
    sex: Option<String>,
}

impl PersonBuilder {
    fn new(name: String, age: u32) -> Self {
        Self {
            name,
            age,
            address: None,
            sex: None,
        }
    }

    fn with_address(mut self, address: String) -> Self {
        self.address = Some(address);
        self
    }

    fn with_sex(mut self, sex: String) -> Self {
        self.sex = Some(sex);
        self
    }

    fn build(self) -> Person {
        Person {
            name: self.name,
            age: self.age,
            address: self.address,
            sex: self.sex,
        }
    }
}

fn main() {
    let person = PersonBuilder::new("Alice".to_string(), 30)
        .with_address("Wonderland".to_string())
        .with_sex("Female".to_string())
        .build();

    println!("{:?}", person);

    // Access the fields to demonstrate usage
    println!("Name: {}", person.name);
    println!("Age: {}", person.age);
    if let Some(address) = &person.address {
        println!("Address: {}", address);
    } else {
        println!("Address: None");
    }
    if let Some(sex) = &person.sex {
        println!("Sex: {}", sex);
    } else {
        println!("Sex: None");
    }
}
plaintext 复制代码
Person { name: "Alice", age: 30, address: Some("Wonderland"), sex: Some("Female") }
Name: Alice
Age: 30
Address: Wonderland
Sex: Female

使用Bon构建器

了解完Rust如何实现构建器模式后,如果我们想要在实际项目中使用构建器,当然可以不用自己手动实现,可以使用第三方库Bon,引入方式如下

Cargo.toml

toml 复制代码
[dependencies]
bon = "1.1.0"
rust 复制代码
use bon::bon;

#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
    address: Option<String>,
    sex: Option<String>,
}

#[bon] // 使用 Bon 库的宏
impl Person {
    #[builder]
    fn new(name: String, age: u32) -> Self {
        Self {
            name,
            age,
            address: None,
            sex: None,
        }
    }

    #[builder]
    fn with_address(&mut self, address: String) {
        self.address = Some(address);    
    }

    #[builder]
    fn with_sex(&mut self, sex: String) {
        self.sex = Some(sex);
    }
}

fn main() {
    let mut person = Person::builder()
        .name("Alice".to_string())
        .age(30)    
        .build();
  
    person.with_address().address("Wonderland").call();
    person.with_sex().sex("Female").call();

    println!("{:?}", person);

    println!("Name: {}", person.name);
    println!("Age: {}", person.age);
    if let Some(address) = &person.address {
        println!("Address: {}", address);
    } else {
        println!("Address: None");
    }
    if let Some(sex) = &person.sex {
        println!("Sex: {}", sex);
    } else {
        println!("Sex: None");
    }
}
plaintext 复制代码
Person { name: "Alice", age: 30, address: Some("Wonderland"), sex: Some("Female") }
Name: Alice
Age: 30
Address: Wonderland
Sex: Female

运行结果和手动实现方式一致。当然这种方式更为简洁,可以省略很多代码实现,容易维护和阅读,更推荐使用

参考资料3,Bon除了结构体的构建器和关联方法的构建器,还有函数的构建器

rust 复制代码
fn main() {
    #[bon::builder] 
    fn greet(name: &str, age: u32) -> String {
        format!("Hello {name} with age {age}!")
    }

    let greeting = greet()
        .name("Bon") 
        .age(24)   
        .call();

    if greeting == "Hello Bon with age 24!" {
        println!("Assertion passed: {}", greeting);
    } else {
        println!("Assertion failed");
    }
}
plaintext 复制代码
Assertion passed: Hello Bon with age 24!

参考

  1. How to do named function arguments in Rust
  2. Rust 中的建造者模式 (qq.com)
  3. Overview | Bon (elastio.github.io)
相关推荐
王码码20358 小时前
Go语言的测试:从单元测试到集成测试
后端·golang·go·接口
王码码20358 小时前
Go语言中的测试:从单元测试到集成测试
后端·golang·go·接口
嵌入式×边缘AI:打怪升级日志9 小时前
使用JsonRPC实现前后台
前端·后端
小码哥_常9 小时前
从0到1:Spring Boot 中WebSocket实战揭秘,开启实时通信新时代
后端
lolo大魔王10 小时前
Go语言的异常处理
开发语言·后端·golang
IT_陈寒12 小时前
Python多进程共享变量那个坑,我差点没爬出来
前端·人工智能·后端
码事漫谈12 小时前
2026软考高级·系统架构设计师备考指南
后端
AI茶水间管理员13 小时前
如何让LLM稳定输出 JSON 格式结果?
前端·人工智能·后端
其实是白羊13 小时前
我用 Vibe Coding 搓了一个 IDEA 插件,复制URI 再也不用手动拼了
后端·intellij idea
用户83562907805114 小时前
Python 操作 Word 文档节与页面设置
后端·python