Michael D.
Michael D.

Reputation: 39

How to dynamically call a function for the strategy pattern?

I am working on a webapplication in .NET Core with Razor Pages (MVVM) with a form where the user can give me 4 options.

Each of those options perform the same action, but just a little bit different in terms of execution - that's why I'd like to implement the strategy pattern.

Is there a way to dynamically generate the function name in some way? It might be a silly question, but I just understand the basics.

// option = A
// option = B
// option = C
// option = D

public async Task<IActionResult> OnPostAsync()
{

    ...

    var option = Input.Option // from model
    if(option == "A") {
        A.DoAlgorithm(input)
    } else if(option = "B") {
        B.DoAlgorithm(ïnput)
    } else if(option = "c") {
        C.DoAlgorithm(input) 
    } else {
        D.DoAlgorithm(input) 
    }

    ...
}

It feels like I am missing the point here of this pattern if I would do this, so my question is: is there some way to dynamically call a function based on the input option? If I am using the wrong pattern for this, please do correct me.

Upvotes: 1

Views: 1742

Answers (2)

StuartLC
StuartLC

Reputation: 107347

Although you could follow the Gang of Four strategy pattern rote, nowadays there are other tools to do much the same thing without creating factories, and relying on proliferation of classes which inherit subclasses or implementation interfaces, e.g. since functions can now be used as variables, we can provide a map of Actions taking your input type:

public static readonly IDictionary<string, Action<InputType>> HandlerMap = 
    new Dictionary<string, Action<InputType>>
 {
    ["A"] = DoAlgorithmA,
    ["B"] = DoAlgorithmB,
    ["C"] = DoAlgorithmC,
    ["D"] = (input) => Console.WriteLine("Too simple to need a method")
    ...
 };

where InputType is the type of your input variable and DoAlgorithmA etc are simply methods accepting InputType (and if the methods are really concise, you could even use a lambda here), e.g.

public static void DoAlgorithmA(InputType input)
{
    ...
}

Invocation would then look like so:

public async Task<IActionResult> OnPostAsync()
{
    if (HandlerMap.TryGetValue(option, out var algorithm))
    {
         algorithm(input);
    }
    // .. else this isn't a valid option.
}

Upvotes: 3

L0uis
L0uis

Reputation: 721

You can use a factory that creates the strategy based on the option chosen, then have a base strategy class that A,B,C and D extend to perform the specific instance of the algorithm.

Pseudo code:

interface Strategy
{
    void DoAlgorithm()
}

class A : Strategy
{   
}

class B : Strategy
{
}

abstract class Creator
{
 public abstract Strategy FactoryMethod(string option);
}

class ConcreteCreator : Creator
{
 public override Strategy FactoryMethod(string option)
 {
 switch (option)
 {
 case "A": return new A();
 case "B": return new B();
 default: throw new ArgumentException("Invalid type", "option");
 }
 }
}

Upvotes: 1

Related Questions