Rust中的架构模式:如何编写无痛苦的可靠应用程序

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

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

开始课程

为什么Rust中的架构不是奢侈品,而是必需品



当你用Rust编写代码时,类型系统和借用检查器已经为你提供了80%的错误防护。但内存安全仅仅是基础。如果你在这个基础上构建混乱的架构,项目迟早会变成一个相互依赖的迷宫,修改一个模块就会破坏其他十个模块。



Rust中的架构模式并非时尚潮流,也不是面向对象世界的遗留物。它们是经过验证的典型问题解决方案:如何创建一个不会违反不变量的对象?如何连接组件以便可以单独测试它们?如何组织逻辑以便可以在不修改现有代码的情况下进行扩展?



在本文中,我们将通过Rust的实际示例来讨论三组模式(创建型、结构型、行为型)。没有抽象的理论——只有可以直接应用的代码。



创建型模式:正确创建对象



Builder模式——从10个参数的构造函数中拯救你



Rust中没有构造函数重载。如果一个结构体有超过3-4个字段,为所有情况编写一个构造函数就意味着用户必须阅读带有Option和Default的长签名。Builder模式优雅地解决了这个问题。



struct ServerConfig {    host: String,    port: u16,    workers: u8,    enable_tls: bool,    max_connections: u32,}

struct ServerConfigBuilder { host: Option<String>, port: Option<u16>, workers: Option<u8>, enable_tls: Option<bool>, max_connections: Option<u32>,}

impl ServerConfigBuilder { fn new() -> Self { Self { host: None, port: None, workers: None, enable_tls: None, max_connections: None, } }

fn host(mut self, host: &str) -> Self { self.host = Some(host.to_string()); self }

fn port(mut self, port: u16) -> Self { self.port = Some(port); self }

fn workers(mut self, workers: u8) -> Self { self.workers = Some(workers); self }

fn enable_tls(mut self, enable: bool) -> Self { self.enable_tls = Some(enable); self }

fn max_connections(mut self, max: u32) -> Self { self.max_connections = Some(max); self }

fn build(self) -> Result<ServerConfig, String> { Ok(ServerConfig { host: self.host.unwrap_or_else(|| "127.0.0.1".to_string()), port: self.port.unwrap_or(8080), workers: self.workers.unwrap_or(4), enable_tls: self.enable_tls.unwrap_or(false), max_connections: self.max_connections.unwrap_or(100), }) }}

// 使用方式let config = ServerConfigBuilder::new() .host("0.0.0.0") .port(443) .enable_tls(true) .build() .expect("Invalid config");


为什么这在Rust中有效? Builder模式与所有权系统完美结合:方法链消费并返回self,最终的build要么返回准备好的对象,要么返回验证错误。没有可变引用和数据竞争。



工厂模式——当返回类型取决于参数时



想象一下,你需要解析不同的格式:JSON、YAML、TOML。与其在每个地方使用match,不如使用工厂方法。



trait Parser {    fn parse(&self, input: &str) -> Result<serde_json::Value, String>;}

struct JsonParser;impl Parser for JsonParser { fn parse(&self, input: &str) -> Result<serde_json::Value, String> { serde_json::from_str(input).map_err(|e| e.to_string()) }}

struct YamlParser;impl Parser for YamlParser { fn parse(&self, input: &str) -> Result<serde_json::

博客

书籍推荐