Rust is a multi paradigm language. It supports Object Oriented Programming model (traits and dynamic binding), functional programming model (closure, etc) and at the same time straight forward procedural programming model.
It won't force a developer to follow a specific paradigm, rather the developers are free to choose and pick any paradigm they want.
As I have come from a pure Object Oriented world, (C++, Java, Python), my tryst with Rust is mainly through the design patterns of Gang of Four book.
Today, i developed a sample example of Command Pattern using Rust.
Key Components of the Command Pattern:
Command Interface:
- Defines a common interface with a method (usually called
execute
) that all concrete commands must implement. This allows different types of commands to be invoked in a uniform way.
- Defines a common interface with a method (usually called
Concrete Command:
- Implements the command interface and defines the actual behavior. It binds the Receiver (the object that knows how to carry out the operation) to an action. The
execute
method is used to invoke the receiver's method(s).
- Implements the command interface and defines the actual behavior. It binds the Receiver (the object that knows how to carry out the operation) to an action. The
Invoker:
- The invoker (e.g., a
Waiter
in a restaurant analogy) is responsible for triggering the command by calling theexecute
method. It does not know or care about the specifics of the command, only that it can execute it.
- The invoker (e.g., a
Receiver:
- The receiver (e.g., a
Chef
) is the object that performs the actual work. The command will delegate the action to the receiver.
- The receiver (e.g., a
Example Scenario: Restaurant
- Invoker: The Waiter takes an order from the customer and passes it to the chef.
- Command: The FoodCommand tells the chef what food to prepare.
- Receiver: The Chef is responsible for actually preparing the food.
The advantage of the Command Pattern is that the Waiter
(invoker) doesn’t need to know the details of how food is prepared. It just knows how to pass the command. You could have different kinds of commands (e.g., DrinkCommand
, FoodCommand
, DessertCommand
), and the invoker can execute them all the same way.
Command Pattern Flow:
- The Invoker issues a command.
- The Concrete Command executes the command by calling methods on the Receiver.
- The Receiver performs the action.
trait Command {
fn execute(&self);
}
//Receiver
struct Chef;
impl Chef {
pub(crate) fn prepare_food(&self) {
println!("Chef is preparing the food...");
}
}
struct FoodCommand{
chef : Chef,
}
impl Command for FoodCommand {
fn execute(&self) {
self.chef.prepare_food();
}
}
//Invoker
struct Waiter {
command : Box<dyn Command>,
}
impl Waiter {
fn new () -> Waiter{
let waiter = Waiter {
command : Box::new (FoodCommand {chef : Chef}),
};
waiter
}
fn pass_command_to_chef(&self){
self.command.execute();
}
}
fn main() {
let chef = Chef;
let food_command = FoodCommand {chef};
let waiter = Waiter {command : Box::new(food_command),};
waiter.pass_command_to_chef();
}
No comments:
Post a Comment