Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to model the strategy pattern in Rust?

I'm looking for a way to implement the strategy pattern in Rust. I wish to implement something similar to this pseudo-code:

class StrategyBase {
    Data data;
    def abstract methodAWorkingOnData();
    def abstract methodBWorkingOnData();
}

class StrategyImplOne {
    def methodAWorkingOnData()
        ... method code ...

    def methodBWorkingOnData()
        ... method code ....
}

class StrategyImplTwo {
    def methodAWorkingOnData()
        ... method code ...

    def methodBWorkingOnData()
        ... method code ....
}

I expected I could have a structure with two traits bound with it, but I can't find a way to implement such a pattern.

like image 969
Vicctor Avatar asked Dec 06 '25 06:12

Vicctor


1 Answers

Combining the definition of the strategy pattern and The Rust Programming Language chapter on Generic Types, Traits, and Lifetimes yields a straightforward result.

Create a trait that represents the common interface and implement the trait a number of times. Then hold a generic type that implements the trait:

struct Context<S> {
    strategy: S,
}

impl<S> Context<S>
where
    S: Strategy,
{
    fn do_things(&self) {
        println!("Common preamble");
        self.strategy.execute();
        println!("Common postamble");
    }
}

trait Strategy {
    fn execute(&self);
}

struct ConcreteStrategyA;

impl Strategy for ConcreteStrategyA {
    fn execute(&self) {
        println!("ConcreteStrategyA")
    }
}

struct ConcreteStrategyB;

impl Strategy for ConcreteStrategyB {
    fn execute(&self) {
        println!("ConcreteStrategyB")
    }
}

fn main() {
    let a = Context {
        strategy: ConcreteStrategyA,
    };
    a.do_things();

    println!("\n---\n");

    let b = Context {
        strategy: ConcreteStrategyB,
    };
    b.do_things();
}

You can use an enum instead of traits if all of your potential implementations are known at compile time.

You still have to contend with any normal Rust design decisions such as ownership, lifetimes, and mutability; none of that is unique.

See also:

  • How can I avoid a ripple effect from changing a concrete struct to generic?
  • Should I use enum to emulate the polymorphism or use trait with Box<trait> instead?
  • How do I create a heterogeneous collection of objects?
like image 68
Shepmaster Avatar answered Dec 08 '25 17:12

Shepmaster



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!