kri*_*nab 5 struct builder rust
我正在查看Rust 文档的方法语法部分,并发现了构建器模式的示例。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);
}
Run Code Online (Sandbox Code Playgroud)
Rust 构建器模式是否必须使用冗余的结构代码?
不。但有时他们可能会。例如,考虑一下我们是否想要在构造函数周围有特殊的逻辑(甚至只是复杂的逻辑):
/// Width must always be greater than height!
struct HorizontalEllipse {
width: f64,
height: f64,
}
impl HorizontalEllipse {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.width / 2.0) * (self.height / 2.0)
}
}
struct HorizontalEllipseBuilder {
width: f64,
height: f64,
}
impl HorizontalEllipseBuilder {
fn new() -> HorizontalEllipseBuilder {
HorizontalEllipseBuilder {
width: 0.0,
height: 0.0,
}
}
fn width(&mut self, width: f64) -> &mut HorizontalEllipseBuilder {
self.width = width;
self
}
fn height(&mut self, height: f64) -> &mut HorizontalEllipseBuilder {
self.height = height;
self
}
fn finalize(&self) -> Result<HorizontalEllipse, String> {
let HorizontalEllipseBuilder { height, width } = *self;
if height >= width {
Err("This is not horizontal".into())
} else {
Ok(HorizontalEllipse { width, height })
}
}
}
fn main() {
let c = HorizontalEllipseBuilder::new()
.width(1.0)
.height(2.0)
.finalize()
.expect("not a valid ellipse");
println!("area: {}", c.area());
println!("width: {}", c.width);
println!("height: {}", c.height);
}
Run Code Online (Sandbox Code Playgroud)
现在aHorizontalEllipse知道这始终是真的width > height。我们已将该检查从许多潜在位置(每个方法)移至构造函数。然后,我们将构造函数移至新类型,因为它很复杂(不是很复杂,但真正复杂的示例通常是......复杂)。
我见过的许多构建器也具有真实对象的“增强”类型:
#[derive(Debug)]
struct Person {
name: String,
}
#[derive(Debug, Default)]
struct PersonBuilder {
name: Option<String>,
}
impl PersonBuilder {
fn name(self, name: &str) -> Self {
PersonBuilder { name: Some(name.into()), ..self }
}
fn build(self) -> Person {
Person {
name: self.name.unwrap_or_else(|| "Stefani Joanne Angelina Germanotta".into()),
}
}
}
fn main() {
let person = PersonBuilder::default().build();
println!("{:?}", person);
let person = PersonBuilder::default().name("krishnab").build();
println!("{:?}", person);
}
Run Code Online (Sandbox Code Playgroud)
您在本书的示例中看不到这一点,因为它试图变得更简单并且不涉及所有权问题。