Search code examples
design-patternsrustdynamic-dispatchstatic-dispatch

How to create a factory method based on static dispatch?


I want to study design pattern use rust language. From this code it works properly but it uses dynamic dispatch. How can I change the code to use static dispatch? Thanks!

trait Shape {
    fn draw(&self);
}

enum ShapeType {
    Rectangle,
    Circle,
}

struct Rectangle {}

impl Shape for Rectangle {
    fn draw(&self) {
        println!("draw a rectangle!");
    }
}

struct Circle {}

impl Shape for Circle {
    fn draw(&self) {
        println!("draw a circle!");
    }
}

struct ShapeFactory;
impl ShapeFactory {
    fn new_shape(s: &ShapeType) -> Box<dyn Shape> {
        match s {
            ShapeType::Circle => Box::new(Circle {}),
            ShapeType::Rectangle => Box::new(Rectangle {}),
        }
    }
}

fn main() {
    let shape = ShapeFactory::new_shape(&ShapeType::Circle);
    shape.draw(); // output: draw a circle!

    let shape = ShapeFactory::new_shape(&ShapeType::Rectangle);
    shape.draw(); // output: draw a rectangle!
}

Solution

  • In the provided example, I would add

    enum StaticShape {
        Rectangle(Rectangle),
        Circle(Circle),
    }
    
    impl Shape for StaticShape {
        fn draw(&self) {
            match self {
                StaticShape::Rectangle(sh) => sh.draw(),
                StaticShape::Circle(sh) => sh.draw(),
            }
        }
    }
    
    struct StaticShapeFactory;
    impl StaticShapeFactory {
        fn new_shape(s: &ShapeType) -> StaticShape {
            match s {
                ShapeType::Rectangle => StaticShape::Rectangle(Rectangle {}),
                ShapeType::Circle => StaticShape::Circle(Circle {}),
            }
        }
    }
    

    and in the main() function

        let shape = StaticShapeFactory::new_shape(&ShapeType::Circle);
        shape.draw(); // output: draw a circle!
    
        let shape = StaticShapeFactory::new_shape(&ShapeType::Rectangle);
        shape.draw(); // output: draw a rectangle!
    

    The StaticShape enum enumerates every possible specific shape that can be handled. In order to behave as a shape, it implements the Shape trait by simply forwarding the call to the specific shape types. The corresponding factory is very similar to the dynamic one; it just builds the specific variant of the returned enum instead of a box.