Builder Patter in Rust: Explained with example

Builder Patter in Rust: Explained with example

Use the Rust Playground, for hands-on learning: https://play.rust-lang.org/

Builder Pattern separates the construction of a complex object from its representation. By doing this, the same construction process can create different representations. The pattern involves a builder class that constructs the final object through a series of method calls.

Let's consider a Circle structure that we want to create using the Builder Pattern. The Circle structure has three attributes: x, y, and radius. Here is the complete code for our example:

1. The Circle Structure

The Circle structure holds the properties of a circle:

struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

impl Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

Here, we define the Circle structure with x, y, and radius attributes. We also implement a method area to calculate the area of the circle.

2. The CircleBuilder Structure

The CircleBuilder structure facilitates the construction of a Circle object:

struct CircleBuilder {
    x: f64,
    y: f64,
    radius: f64,
}

3. Implementing the Builder

The CircleBuilder structure provides methods to set the properties of the circle and a finalize method to create the Circle object:

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,
        }
    }
}
  • new: Initializes the builder with default values.

  • x, y, radius: Set the respective properties and return a mutable reference to the builder.

  • finalize: Creates a Circle object using the set properties.

4. Using the Builder

In the main function, we use the builder to create a Circle object:

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);
}

Here, we chain the builder methods to set the properties of the circle and call finalize to create the Circle object. Finally, we print the area and coordinates of the circle.

Here is the full code:



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 the full code in the Playground here :

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=85bad54ec5dc8c4f778196815041f4fe

https://gist.github.com/rust-play/85bad54ec5dc8c4f778196815041f4fe

Did you find this article valuable?

Support Coolhead by becoming a sponsor. Any amount is appreciated!