Rust中的设计模式:何时以及为何使用它们

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Rust中的设计模式:不仅仅是时尚,更是必要



当我们谈论Rust时,许多人想到的是类型系统、借用检查器以及没有垃圾回收器。但在这严谨的外表之下,隐藏着一个强大的架构设计工具。Rust中的设计模式(design patterns)不仅仅是对Java或C++传统的致敬。这是一种让编译器为你工作、而不是与你作对的方式。



在本文中,我们将探讨为什么经典的GoF(四人帮)模式在Rust中看起来不同,哪些模式真正有用,哪些是反模式。最重要的是,我们将看到可以立即在项目中使用的真实代码。



为什么Rust改变了游戏规则?



经典的设计模式通常解决与内存管理、继承和多态相关的问题。而Rust提供了一种完全不同的方法:



  • 所有权和借用——你显式地管理内存,而不是依赖垃圾回收。在其他语言中解决“谁拥有对象”问题的模式,在Rust中变得微不足道或根本不需要。
  • 特征(Traits)——替代继承。Rust不支持经典的面向对象继承,但trait提供了灵活性,且没有菱形继承问题。
  • 枚举和模式匹配——一个强大的工具,取代了许多与状态和分支相关的模式。
  • 函数式风格——迭代器、闭包和组合器让你无需显式模式即可编写简洁的代码。


因此,Rust中的许多模式看起来不像“类和接口”,而是trait + 结构体 + 枚举。让我们看看具体的例子。



Builder模式:构建复杂对象



Builder模式是Rust中最流行的模式之一。它非常适合创建具有大量参数的对象,尤其是当其中一些参数是可选的时。



问题:带有10个参数的构造函数



想象一下,你需要创建一个HTTP客户端配置。在传统方法中,你会这样写:



let client = HttpClient::new(    "https://api.example.com",    Duration::from_secs(30),    5,    true,    None,    vec!["Accept: application/json".to_string()],    ...);


这难以阅读,并且很容易弄错参数的顺序。Builder解决了这个问题。



在Rust中的实现



在Rust中,Builder模式通过一个单独的结构体来实现,该结构体包含返回self的setter方法:



#[derive(Debug)]pub struct HttpClient {    base_url: String,    timeout: Duration,    max_retries: u32,    verify_ssl: bool,    headers: Vec<String>,}

pub struct HttpClientBuilder { base_url: String, timeout: Duration, max_retries: u32, verify_ssl: bool, headers: Vec<String>,}

impl HttpClientBuilder { pub fn new(base_url: &str) -> Self { HttpClientBuilder { base_url: base_url.to_string(), timeout: Duration::from_secs(30), max_retries: 3, verify_ssl: true, headers: Vec::new(), } }

pub fn timeout(mut self, duration: Duration) -> Self { self.timeout = duration; self }

pub fn max_retries(mut self, n: u32) -> Self { self.max_retries = n; self }

pub fn no_ssl(mut self) -> Self { self.verify_ssl = false; self }

pub fn add_header(mut self, header: &str) -> Self { self.headers.push(header.to_string()); self }

pub fn build(self) -> Result<HttpClient, String> { if self.base_url.is_empty() { return Err("base_url cannot be empty".to_string()); } Ok(HttpClient { base_url: self.base_url,

博客

书籍推荐