Mediator Design pattern in Rust

Mediator pattern is used to reduce communication complexity between multiple objects or classes.

This pattern provides a mediator class that normally handles all the communications between different classes and supports easy maintenance of the code by loose coupling. The mediator pattern falls under the behavioral pattern category.

The problem

In case we have many objects that interact with each other, we end up with very complex and non-maintainable code. That’s why it is a good case to use the Mediator design pattern.

There are many times that we have interaction among objects. We usually create a sufficient amount of objects allowing to communicate with each other with the intention of building entities that act together for a specific reason.

When something happens to an object then another one has to do something or change its behavior.

Building a complex code allowing many objects (2 or more) to communicate with each other, you will end up with spaghetti code, non-maintainable, and you will face a nightmare every time you want to find and fix a bug or to enhance the code.

This problem increases if you normally have a back and forth and a complex interaction

How do we solve it

The solution comes using the Mediator pattern. This pattern allows you to keep the whole logic of communication in one place (object) and every object used to interact with other objects now interacts only with the one which is aware of how to act in every occasion.

So, we can understand very quickly that objects are decoupled. The code is more simple than it used to be. That’s exactly what we try to achieve using OOP and design patterns.

Real-time Example for Rust Mediator Design Pattern

An air traffic controller (ATC) is a mediator between flights. It helps in communication between flights and co-ordinates/controls landing, take-off.

Two flights need not interact directly and there is no dependency between them. This dependency is solved by the mediator ATC.

If ATC is not there all the flights have to interact with one another and managing the show will be very difficult and things may go wrong.

// Mediator pattern

use std::collections::HashMap;

pub fn mediator() { let mut mediator = Mediator::new();
let label1 = String::from("Nyan"); let label2 = String::from("Piyo"); let node1 = Node::new(&label1); let node2 = Node::new(&label2);
mediator.add_node(node1); mediator.add_node(node2);
let n1 = mediator.get(&label1); n1.send_msg(&mediator, &label1, "hi from Nyan"); let n2 = mediator.get(&label2); n2.send_msg(&mediator, &label2, "hi from Piyo"); }

struct Mediator { nodes: HashMap<String, Node>, }

impl Mediator { fn new() -> Self { Self { nodes: HashMap::new(), } }
fn add_node(&mut self, node: Node) { self.nodes.insert(node.label.clone(), node); }
fn consult_to(&self, label: &str, msg: &str) { self.nodes[label].receive_msg(msg); }
fn get(&self, label: &str) -> &Node { &self.nodes[label] } }

struct Node { label: String, }

impl Node { fn new(label: &str) -> Self { Self { label: label.to_string(), } }
fn send_msg(&self, mediator: &Mediator, target_label: &str, msg: &str) { mediator.consult_to(target_label, msg); }
fn receive_msg(&self, msg: &str) { println!("{} received message: {}", self.label, msg); } }

Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions