根据以下示例,可以在Rust中使用链式方法调用编写构建模式,该方法调用通过值传递或通过引用传递(使用生命周期说明符)
Rust中的构建器模式可能如下所示:
ui::Button::new()
.label("Test")
.align(Align::Center)
.build();
写作惯用语时,是否有一种强烈的偏好?
是否有一些很好的例子说明如何在Rust中写这个?
答案 0 :(得分:5)
实际上有两个权衡:
self
?build
方法应该通过值或引用接受self
吗?我的建议是:
build
方法的值这与使用build
中的引用的Rust Book中提供的Builder Pattern略有不同。
为什么要通过setter的可变引用传递?
虽然编译器可以优化调用fn label(self, &str) -> ButtonBuilder
所引起的移动,但不能保证。
另一方面,可变参考方式已经是最优的,因此您无需依赖优化器。
为什么要通过最终build
的值?
对于仅由Copy
字段组成的构建器,build
或self
&self
之间没有区别。
但是,只要构建器包含非Copy
字段,将&self
传递给build
就需要深度克隆这些字段。
另一方面,按值self
传递build
可以移动字段,从而避免不必要的副本。
如果希望重新使用构建器,那么构建器应该实现Clone
。
答案 1 :(得分:1)
我已经看到构建器模式主要是通过在修改它时获取Builder的所有权来实现的,并且通过build()
的引用来实现。例如,
#[derive(Debug, Eq, PartialEq)]
struct Foo {
value: usize,
}
struct FooBuilder {
foos: usize,
bars: usize,
}
impl FooBuilder {
fn new() -> FooBuilder {
FooBuilder {
foos: 0,
bars: 0,
}
}
fn set_foos(mut self, foos: usize) -> FooBuilder {
self.foos = foos;
self
}
fn set_bars(mut self, bars: usize) -> FooBuilder {
self.bars = bars;
self
}
fn build(&self) -> Foo {
Foo {
value: self.foos + self.bars,
}
}
}
fn main() {
let foo = FooBuilder::new()
.set_foos(2)
.set_bars(3)
.build();
assert_eq!(foo, Foo { value: 5 });
}
这使链接变得简单,同时允许重用构建器。