# Strategy pattern

It's a behavioral pattern which turns possible changes in behavior accordingly to the chosen strategy.

## Structure

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690383574509/a858dec6-4f0d-45be-88a8-f8d0d7def3dc.png align="center")

### 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

```rust
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
