Strategy pattern
Table of contents
It's a behavioral pattern which turns possible changes in behavior accordingly to the chosen strategy.
Structure
Context
The use of context is recommended so that the client does not need to know the implementation details of each strategy. It can facilitate in using a default strategy and one can change strategies through it at runtime.
Pros
Reduces the use of conditionals
A more dynamic change in behavior
Cons
Clients need to know what strategy to use
Implementation
use std::any::Any;
use std::collections::HashMap;
use std::iter::Map;
use maplit::hashmap;
fn main() {
let mut m = MarshallerContext::new(Box::new(JsonMarshaller{}));
let example_map: HashMap<&str, &str> = hashmap! {
"one" => "1",
"two" => "2",
};
let json_output = m.marshall(&example_map);
println!("json output:\n {}", json_output);
m.strategy = Box::new(XmlMarshaller{});
let xml_output = m.marshall(&example_map);
println!("xml output:\n {}", xml_output);
}
pub trait Marshaller {
fn marshall(&self, response: &HashMap<&str, &str>) -> String;
}
struct JsonMarshaller {
}
//A very simple example without recursive attributes
impl Marshaller for JsonMarshaller {
fn marshall(&self, response: &HashMap<&str, &str>) -> String {
return response.iter().fold(String::new(), |mut acc, (k, v)| {
acc.push_str(&format!("{}: {}\n", k, v));
acc
})
}
}
struct XmlMarshaller {
}
//A very simple example without recursive attributes
impl Marshaller for XmlMarshaller {
fn marshall(&self, response: &HashMap<&str, &str>) -> String {
return response.iter().fold(String::new(), |mut acc, (k, v)| {
acc.push_str(&format!("<{}>{}</{}>\n", k, v, k));
acc
})
}
}
struct MarshallerContext {
strategy: Box<dyn Marshaller>
}
impl MarshallerContext {
fn new(strategy: Box<dyn Marshaller>) -> Box<Self> {
Box::new(MarshallerContext{ strategy })
}
fn marshall(&self, response: &HashMap<&str, &str>) -> String {
//we can do some stuff here. Like select a default strategy, prepare the string etc.
self.strategy.marshall(response)
}
}
Sources
Design patterns
Elements of Reusable Object-Oriented Software
Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides