Design Patterns in Rust Programming

Reading Time: 3 minutes

The Design Patterns are programming language independent strategies for solving a common problem. By using design patterns, you can make your code more flexible, reusable, and maintainable. These solutions were obtained by trial and error by numerous software developers.

Types of Design Patterns

There are following types of design Patterns in Rust for solving our problems :

  • Behavioural
  • Creational

Behavioural Patterns

Behavioural design pattern are design patterns that identify common communication patterns among objects. These patterns characterise complex control flow that’s difficult to follow at run-time. There are following types of Behavioural Pattern :

  • Command
  • Interpreter
  • Strategy

Command

Command is a behavioural design pattern that turns a request into a stand-alone object. The basic idea of the Command pattern is to separate out actions into its own objects and pass them as parameters.

pub trait Migration {
    fn execute(&self) -> &str;
    fn rollback(&self) -> &str;
}

pub struct CreateTable;
impl Migration for CreateTable {
    fn execute(&self) -> &str {
        "create table"
    }
    fn rollback(&self) -> &str {
        "drop table"
    }
}

Interpreter

The Interpreter pattern is a design pattern that specifies how to evaluate sentences in a language. The Interpreter pattern describes how to define a grammar for simple languages.

Strategy

The Strategy design pattern is a technique that enables separation of concerns. It provides a substitute to sub classing. The main advantage is separation of concerns.

use std::collections::HashMap;

type Data = HashMap<String, u32>;

trait Formatter {
    fn format(&self, data: &Data, buf: &mut String);
}

struct Report;

impl Report {
    fn generate<T: Formatter>(gen: T, str: &mut String) {
        let mut data = HashMap::new();
        data.insert("one".to_string(), 1);
        data.insert("two".to_string(), 2);
        gen.format(&data, str);
    }
}

struct Text;
impl Formatter for Text {
    fn format(&self, data: &Data, buf: &mut String) {
        for (key, value) in data {
            let entry = format!("{} {}\n", key, value);
            buf.push_str(&entry);
        }
    }
}

struct Json;
impl Formatter for Json {
    fn format(&self, data: &Data, buf: &mut String) {
        buf.push('[');
        for (key, value) in data.into_iter() {
            let entry = format!(r#"{{"{}":"{}"}}"#, key, value);
            buf.push_str(&entry);
            buf.push(',');
        }
        buf.pop(); 
        buf.push(']');
    }
}

fn main() {
    let mut str = String::from("");
    Report::generate(Text, &mut str);
    assert!(str.contains("one 1"));
    assert!(str.contains("two 2"));

    str.clear(); 
    Report::generate(Json, &mut str);
    assert!(str.contains(r#"{"one":"1"}"#));
    assert!(str.contains(r#"{"two":"2"}"#));
}

Creational Patterns

Creational pattern provide various object creation mechanisms, which increase flexibility and reuse of existing code. There are following types of Creational Pattern :

  • Builder
  • Fold

Builder

Builder pattern builds a complex object using simple objects. The pattern allows you to produce different types and representations of an object using the same construction code.

fn main() {
#[derive(Debug, PartialEq)]
pub struct Foo {
    bar: String,
}

impl Foo {
    pub fn builder() -> FooBuilder {
        FooBuilder::default()
    }
}

#[derive(Default)]
pub struct FooBuilder {
    bar: String,
}

impl FooBuilder {
    pub fn new(/* ... */) -> FooBuilder {
        FooBuilder {
            bar: String::from("X"),
        }
    }

    pub fn name(mut self, bar: String) -> FooBuilder {
        self.bar = bar;
        self
    }

    pub fn build(self) -> Foo {
        Foo { bar: self.bar }
    }
 }
}

Fold

Run an algorithm over each item in a collection of data to create a new item, thus creating a whole new collection. It is common to want to map a data structure by performing some operation on each node in the structure.

Thanks for Reading !!

If you want to read more content like this?  Subscribe to Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe to Rust Times Newsletter: https://bit.ly/2Vdlld7.


Knoldus-blog-footer-image

Written by 

I am Software Consultant at Knoldus and I am curious about learning new technologies.