Я создаю функциональный конструктор, который настраивает объект, например:
struct Person
{
name: String,
position: String
}
Сам конструктор хранит список закрытых окон, которые будут применяться к объекту, когда его нужно создать:
struct FunctionalBuilder<TSubject>
where TSubject : Default
{
actions: Vec<Box<dyn Fn(&mut TSubject) -> ()>>
}
impl<TSubject> FunctionalBuilder<TSubject>
where TSubject : Default
{
fn build(self) -> TSubject
{
let mut subj = TSubject::default();
for action in self.actions
{
(*action)(&mut subj);
}
subj
}
}
Идея состоит в том, что можно агрегировать этот построитель, а затем настроить его для такого объекта, как Person
. Теперь предположим, что я хочу иметь метод построения called()
, который принимает имя и сохраняет присвоенное имя в закрытии. Я реализую это следующим образом:
impl PersonBuilder
{
pub fn called(mut self, name: &str) -> PersonBuilder
{
let value = name.to_string();
self.builder.actions.push(Box::new(move |x| {
x.name = value.clone();
}));
self
}
}
Это правильный способ работы? Есть ли лучший способ избежать использования временной переменной и вызова clone()
?
Полный рабочий пример:
#[derive(Debug, Default)]
struct Person {
name: String,
position: String,
}
struct FunctionalBuilder<TSubject>
where
TSubject: Default,
{
actions: Vec<Box<dyn Fn(&mut TSubject) -> ()>>,
}
impl<TSubject> FunctionalBuilder<TSubject>
where
TSubject: Default,
{
fn build(self) -> TSubject {
let mut subj = TSubject::default();
for action in self.actions {
(*action)(&mut subj);
}
subj
}
fn new() -> FunctionalBuilder<TSubject> {
Self {
actions: Vec::new(),
}
}
}
struct PersonBuilder {
builder: FunctionalBuilder<Person>,
}
impl PersonBuilder {
pub fn new() -> Self {
PersonBuilder {
builder: FunctionalBuilder::<Person>::new(),
}
}
pub fn called(mut self, name: &str) -> PersonBuilder {
let value = name.to_string();
self.builder.actions.push(Box::new(move |x| {
x.name = value;
}));
self
}
pub fn build(self) -> Person {
self.builder.build()
}
}
pub fn main() {
let builder = PersonBuilder::new();
let me = builder.called("Dmitri").build();
println!("{:?}", me);
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=27eb6283836a478d5c68aa025aa4698d