Strategy Pattern
The strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. This pattern lets the algorithm vary independently from clients that use it.
Here's an example:
// Strategy type pub trait Strategy { fn execute(&self, data: &str); } pub struct ConcreteStrategyA; // Concrete Strategy A impl Strategy for ConcreteStrategyA { fn execute(&self, data: &str) { println!("ConcreteStrategyA: {}", data); } } pub struct ConcreteStrategyB; // Concrete Strategy B impl Strategy for ConcreteStrategyB { fn execute(&self, data: &str) { println!("ConcreteStrategyB: {}", data); } } // Context type pub struct Context { strategy: Box<dyn Strategy>, } // Concrete Context impl Context { pub fn new(strategy: Box<dyn Strategy>) -> Self { Context { strategy } } pub fn set_strategy(&mut self, strategy: Box<dyn Strategy>) { self.strategy = strategy; } pub fn execute_strategy(&self, data: &str) { self.strategy.execute(data); } } fn main() { let strategy_a = Box::new(ConcreteStrategyA); let strategy_b = Box::new(ConcreteStrategyB); let mut context = Context::new(strategy_a); context.execute_strategy("Hello, World!"); context.set_strategy(strategy_b); context.execute_strategy("Hello, Rust!"); }
In this example:
- Strategy Trait: Defines a common interface for all supported algorithms.
- Concrete Strategies: Implement the Strategy trait for different algorithms.
- Context: Maintains a reference to a Strategy object and is configured with a Concrete Strategy object.
- Main Function: Creates instances of different strategies and the context, then executes the strategies within the context.
This pattern is useful for scenarios where you need to switch between different algorithms or behaviors at runtime.