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)
相关推荐
长栎38 分钟前
写 for 循环写了十年,你却从没用过迭代器模式最狠的那一面
后端
LiaCode42 分钟前
Redis 在生产项目的使用
前端·后端
用户559822481221 小时前
Docker Compose Down 导致容器数据误删——ext4 日志恢复全记录
后端
LiaCode1 小时前
一天学完 redis 的爽翻版核心知识总结
前端·后端
大刚测试开发实战1 小时前
如何内网穿透访问本地私有化部署的TestHub
前端·后端·github
xiaodaoluanzha1 小时前
迄今為止,最簡單的編程語言 Nolang
前端·后端
Csvn1 小时前
Docker 容器管理入门 — 从镜像到容器编排
后端
用户762352425911 小时前
ShardingJDBC
后端
行者全栈架构师1 小时前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
Colin草率地做慢慢地改1 小时前
关于QuickStore这个项目的重构(2)- 数据库建表文件
后端·面试·架构