Design Patterns

Hello! I am new to rust :slight_smile: less than a week, i came here to ask if somebody could convert design patterns from this book:https://www.tutorialspoint.com/design_pattern/design_pattern_tutorial.pdf into rust as it would be good for learning new guys like me.
If somebody haves somewhere anything alike that please do post a link. I found one but it haves only 2 patterns and seems to be outdated.

Would be cool to see some examples in rust from this book to:http://bit.ly/2iSJqk4
I think this would be really beneficial for the rust beginners.
Thanks!

3 Likes

Hi! In general, it will be difficult to apply standard object oriented design pattern to Rust code.

I have some links for you, tough :slight_smile:

https://github.com/rust-unofficial/patterns

https://github.com/ctjhoa/rust-learning

4 Likes

Many thanks,checking that now :smiley:

I'm interested in helping to create a smoother path from Java/JVM users over to rust, so I gave the Factory pattern one a go.

Note that I did not go for the most elegant/terse approach, and am deliberately avoiding more advanced features, but this might help get you started:


/// Equivalent to the interface in java
/// Traits are more like scala's traits than java's interfaces,
/// due to the fact that they can include implementations, and not just
/// abstract interfaces, but here we are not using that facility.
/// Renamed to ShapeLike to not collide with the concrete enum Shape below
pub trait ShapeLike {
    fn draw(&self);
}

/// This is an additional artifact not present in java
/// Because of Rust's low level nature, and the importance of knowing
/// the size of types in advance, it's often far easier to return
/// an enum than an abstract trait.
/// The only downside is that if you add a new type, you need to add a new
/// item to the enum.
#[derive(Debug)]
pub enum Shape {
    Rectangle(Rectangle),
    Square(Square),
    Circle(Circle),
}

/// Our enum that can contain any of the shapes also behaves like a shape
impl ShapeLike for Shape {
    fn draw(&self) {
        match *self {
            Shape::Rectangle(ref rectangle) => rectangle.draw(),
            Shape::Square(ref square) => square.draw(),
            Shape::Circle(ref circle) => circle.draw(),
        }
    }
}

#[derive(Debug)] //Derive debug should be on nearly every struct and enum
pub struct Rectangle {}
// you would store the fields of your respective shapes inside these structs
#[derive(Debug)]
pub struct Square {}
#[derive(Debug)]
pub struct Circle {}



impl ShapeLike for Rectangle {
    fn draw(&self) {
        println!("inside Rectangle::draw()")
    }
}

impl ShapeLike for Square {
    fn draw(&self) {
        println!("inside Square::draw()")
    }
}

impl ShapeLike for Circle {
    fn draw(&self) {
        println!("inside Circle::draw()")
    }
}


/// Factories are not very idiomatic in rust, but leaving this as is
/// Consider using "builder" terminology instead of factory
pub struct ShapeFactory {}

impl ShapeFactory {
    pub fn get(shape: &str) -> Shape {
        match shape.as_ref() {
            "CIRCLE" => Shape::Circle(Circle {}),
            "SQUARE" => Shape::Square(Square {}),
            "RECTANGLE" => Shape::Rectangle(Rectangle {}),
            &_ => unimplemented!(),
        }
    }
}

fn main() {
    let circle = ShapeFactory::get("CIRCLE");
    let square = ShapeFactory::get("SQUARE");
    let rectangle = ShapeFactory::get("RECTANGLE");

    println!("circle: {:?}", circle);
    println!("square: {:?}", square);
    println!("rectangle: {:?}", rectangle);

    circle.draw();
    square.draw();
    rectangle.draw();

}
1 Like

Cool thanks! I know Python and some C,C++,C#,Java, i am planing to convert these python design patterns to Rust as soon as i learn syntax well :smiley:
These i converted from one Java book:https://github.com/JosipHaboic/python-design-patterns and hoping to make Rust version as soon as possible :D.
Could maybe someone show of example for Composite?
Thanks!

Hey, I don't mean to nitpick - I think your examples are great. But, I think that Rust does actually implement the Factory pattern, albeit expressed a different way. The new() method idiot is a good way to achieve the intended result that's expressed in that tutorial, e.g.

In Factory pattern, we create objects without exposing the creation logic to the client and refer to newly created object using a common interface.

https://www.tutorialspoint.com/design_pattern/design_pattern_tutorial.pdf, p9

I would argue that the "Factory pattern" is not intended as template code, but as an abstract concept that might take many forms. In Rust I believe those three factories would look like this:

impl Shape {
  fn new_circle() -> Shape {
    Shape::Circle( Circle {} )
  }

  fn new_square() -> Shape {
    Shape::Square( Square {} )
  }

  fn new_rectangle() -> Shape {
    Shape::Rectangle( Rectangle {} )
  }
}

fn main() {
    let r = Shape::new_rectangle();
    println!("{:#?}", r);
}

Maybe I've got this wrong (am not really a Java dev) Really sorry if this has derailed the thread! Your code is certainly a much better transliteration of the Java code!

lol funny typo :smiley:
Thanks on your response and your's example, Python is easy it wasnt a problem to translate the patterns,
translating them to Rust seems a bit more challenge :smiley:

This stuff is also very good reading,if somebody would be willing to show some example in Rust that would be great:Patterns of Enterprise Application Architecture.pdf

I typed up a blog post: https://cberhard.wordpress.com

About the "Abstract Factory Pattern"… this is why and how to make fun of Java sometimes. There may be a situation in which this "pattern" is useful, but they are so rare, that you really should not include that construction in a "how to program" PDF. This belongs into the PDF about "How not to program unless you can absolutely not avoid it".

Thanks! This kind of code is what i look for.

I gave the Factory pattern one a go.

I really like this approach. I saw some others reply with comments and disagree slightly with their assessment. This implementation hides the nuances from the consumer which means the code is less fragile and more maintainable (aka SOLID). Thnx for the post.