Rust设计模式:高级示例与实战
\n\n设计模式是经过验证的典型问题解决方案,有助于创建灵活、可维护且可扩展的架构。在Rust中,凭借其所有权、借用和特质系统,许多经典模式具有独特的实现方式。本文将深入剖析在Rust生态系统中特别高效的高级设计模式。
\n\n1. 高级Builder(建造者)模式
\n\n经典的Builder模式在Rust中通常通过返回&mut Self的方法链来实现。然而,在高级层面,我们使用带状态类型的类型化Builder,以确保在编译阶段的正确性。
问题:必填字段的控制
\n普通的Builder无法保证用户填写了所有必填字段。我们可能会忘记调用.build()或未设置关键参数。
解决方案:带幽灵类型的Builder
\nuse std::marker::PhantomData;\n\n// 字段的状态类型\nstruct UsernameNotSet;\nstruct UsernameSet;\nstruct PasswordNotSet;\nstruct PasswordSet;\n\nstruct UserBuilder<U, P> {\n username: Option<String>,\n password: Option<String>,\n _username: PhantomData<U>,\n _password: PhantomData<P>,\n}\n\nimpl UserBuilder<UsernameNotSet, PasswordNotSet> {\n pub fn new() -> Self {\n Self {\n username: None,\n password: None,\n _username: PhantomData,\n _password: PhantomData,\n }\n }\n}\n\nimpl<P> UserBuilder<UsernameNotSet, P> {\n pub fn username(mut self, name: &str) -> UserBuilder<UsernameSet, P> {\n self.username = Some(name.to_string());\n UserBuilder {\n username: self.username,\n password: self.password,\n _username: PhantomData,\n _password: PhantomData,\n }\n }\n}\n\nimpl<U> UserBuilder<U, PasswordNotSet> {\n pub fn password(mut self, pwd: &str) -> UserBuilder<U, PasswordSet> {\n self.password = Some(pwd.to_string());\n UserBuilder {\n username: self.username,\n password: self.password,\n _username: PhantomData,\n _password: PhantomData,\n }\n }\n}\n\nimpl UserBuilder<UsernameSet, PasswordSet> {\n pub fn build(self) -> User {\n User {\n username: self.username.expect("Username must be set"),\n password: self.password.expect("Password must be set"),\n }\n }\n}\n\npub struct User {\n pub username: String,\n pub password: String,\n}\n\nfn main() {\n // 现在编译器不允许在未设置两个字段的情况下调用build()\n let user = UserBuilder::new()\n .username("alice")\n .password("secret123")\n .build();\n println!("User: {}", user.username);\n}\n\n优势:"忘记字段"的错误在编译阶段被检测到,而非运行时。
\n\n2. 通过特质实现的State(状态)模式
\n\nState模式允许对象在内部状态改变时改变其行为。在Rust中,这可以通过枚举(enum)和特质优雅地实现。
\n\n使用枚举的实现
\nenum ConnectionState {\n Disconnected,\n Connecting,\n Connected,\n}\n\nstruct Connection {\n state: ConnectionState,\n}\n\nimpl Connection {\n pub fn new() -> Self {\n Self { state: ConnectionState::Disconnected }\n }\n\n pub fn connect(&mut self) {\n match self.state {\n ConnectionState::Disconnected => {\n println!("开始连接...");\n self.state = ConnectionState::Connecting;\n }\n ConnectionState::Connecting => {\n printl