Rust中Builder轻量模式


在这篇简短的文章中,我描述并命名了构建器模式的表亲——builder lite。
与使用单独的构建器对象的传统构建器不同,构建器精简版重用对象本身来提供构建器功能。
这是一个builder lite说明性示例

pub struct Shape {
  position: Vec3,
  geometry: Geometry,
  material: Option<Material>,
}

impl Shape {
  pub fn new(geometry: Geometry) -> Shape {
    Shape {
      position: Vec3::default(),
      geometry,
      material: None,
    }
  }

  pub fn with_position(mut self, position: Vec3) -> Shape {
    self.position = position;
    self
  }

  pub fn with_material(mut self, material: Material) -> Shape {
    self.material = Some(material);
    self
  }
}

// Call site

let shape = Shape::new(Geometry::Sphere::with_radius(1))
  .with_position(Vec3(0, 9, 2))
  .with_material(Material::SolidColor(Color::Red));

builder-lite 的主要好处是它是new方法的增量、零成本演进。因此,它在代码快速发展、方向不确定的情况下特别有用。也就是说,在构建应用程序而不是库时适用。

相比之下,完全的构建器builder在定义站点要冗长得多,并且需要在调用站点进行一些额外的调用,如下:

pub struct Shape {
  position: Vec3,
  geometry: Geometry,
  material: Option<Material>,
}

pub struct ShapeBuilder {
  position: Option<Vec3>,
  geometry: Option<Geometry>,
  texture: Option<Texture>,
}

impl Shape {
  pub fn builder() -> ShapeBuilder { ... }
}

impl ShapeBuilder {
  pub fn position(&mut self, position: Vec3) -> &mut Self { ... }
  pub fn geometry(&mut self, geometry: Geometry) -> &mut Self { ... }
  pub fn material(&mut self, material: Material) -> &mut Self { ... }
  pub fn build(&self) -> Shape { ... }
}

// Call site

let shape = Shape::builder()
  .position(Vec3(9, 2))
  .geometry(Geometry::Sphere::with_radius(1))
  .material(Material::SolidColor(Color::Red))
  .build();