我正在查看Method syntax section of the Rust documentation,偶然发现了构建器模式的一个示例。下面示例中的CircleBuilder
结构体是Circle
结构体的精确副本。看起来这些多余的代码违反了编程的通常规范。
我理解为什么这个例子创建了一个新的结构体,因为创建者不想对原始的Circle
结构体实现构建器方法。这很好,但是有没有一种方法可以重写这个示例,使其没有冗余,同时仍然保持main()
函数中的良好构建器接口不变?
我试图创建一个空结构体或一个只包含一个一次性元素的结构体,但这不起作用。
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
struct CircleBuilder {
x: f64,
y: f64,
radius: f64,
}
impl CircleBuilder {
fn new() -> CircleBuilder {
CircleBuilder { x: 0.0, y: 0.0, radius: 1.0, }
}
fn x(&mut self, coordinate: f64) -> &mut CircleBuilder {
self.x = coordinate;
self
}
fn y(&mut self, coordinate: f64) -> &mut CircleBuilder {
self.y = coordinate;
self
}
fn radius(&mut self, radius: f64) -> &mut CircleBuilder {
self.radius = radius;
self
}
fn finalize(&self) -> Circle {
Circle { x: self.x, y: self.y, radius: self.radius }
}
}
fn main() {
let c = CircleBuilder::new()
.x(1.0)
.y(2.0)
.radius(2.0)
.finalize();
println!("area: {}", c.area());
println!("x: {}", c.x);
println!("y: {}", c.y);
}
3条答案
按热度按时间ve7v8dk21#
Rust构建器模式必须使用冗余结构代码吗?
不。但有时候他们可能会。例如,考虑我们是否希望在构造函数周围有特殊的逻辑(甚至只是复杂的逻辑):
现在一个
HorizontalEllipse
知道width > height
总是真的。我们已经将检查从许多可能的地方(每个方法)移到了一个地方,即构造函数。然后我们将构造函数移到一个新的类型,因为它很复杂(不是真的,但真正复杂的例子通常是...复杂)。我见过的许多构建器也有真实的对象的“增强”类型:
你在书中的例子中看不到这一点,因为它试图更简单,不涉及所有权问题。
ivqmmu1c2#
这似乎是一个宏可以做的事情。快速搜索找到了似乎实现了此功能的derive_builder和builder_macro板条箱。
yyhrrdl83#
我创建了一个名为
default-struct-builder
的宏crate,旨在避免生成单独的构建器结构,甚至是build()
方法。它的目的是在简单的情况下用于实现构造函数(就像您所做的那样)或
Default
的结构。你可以像这样把它添加到你的结构体中:
然后像这样简单地使用它: