5 个让你写出更好 Rust 代码的 Pattern
CAUTION
Builder
通常用于可以以多种方式构造的对象,提供比较高的可扩展性
struct BurgerBuilder {
components: Vec<BurgerComponent>,
}
enum BurgerComponent {
BottomBun,
Patty,
Tomato,
Cheese,
Lettuce,
TopBun,
}
impl BurgerBuilder {
fn new() -> BurgerBuilder {
BurgerBuilder {
components: vec![BurgerComponent::BottomBun],
}
}
pub fn add_component(mut self, component: BurgerComponent) -> BurgerBuilder {
self.coponents.push(component);
self
}
pub fn build(mut self) -> BurgerBuilder {
self.components.push(BurgerComponent::TopBun);
self
}
}
let burger = BurgerBuilder::new()
.add_component(BurgerComponent::Patty)
.add_component(BurgerComponent::Tomato)
.add_component(BurgerComponent::Cheese)
.add_component(BurgerComponent::Lettuce)
.build();
Factory
通常会抽象复杂的对象为一个简单的接口。传统 OOP
trait Toy {
fn log(&self);
}
struct Robot;
struct Car;
impl Toy for Robot {
fn log(&self) {
println!("Robot");
}
}
impl Toy for Car {
fn log(&self) {
println!("Car");
}
}
enum ToyType {
Robot,
Car,
}
struct Factory;
impl Factory {
fn build_toy(toy_type: ToyType) -> Box<dyn Toy> {
match toy_type {
ToyType::Robot => Box::new(Robot),
ToyType::Car => Box::new(Car),
}
}
}
RAII
这个没什么好说的。
TypeState
可以用 type 来管理对象的状态,在编译期就可以保证类型安全。经典的类型体操。
struct File<State> {
state: State,
}
struct Closed;
struct Open;
impl File<Closed> {
fn open(self) -> File<Open> {
println!("Opening file");
File { state: Open }
}
}
impl File<Open> {
fn close(self) -> File<Closed> {
println!("Closing file");
File { state: Closed }
}
fn read(&self) {
println!("Reading file");
}
fn write(&self) {
println!("Writing file");
}
}
fn main() {
let file = File { state: Closed };
let file = file.open();
file.read();
let file = file.close();
}
New Type
把 primitive 类型包装为一个 struct。
比较简单,总之就是别想着你那个 primitive type 了,都来玩类型体操。