4

Using the strategy pattern, how can treat different exectute methods differently in terms of them having different parameters?

3 example strategies

public function execute(string $param1, string $param2)
{
    // Do something specific to this method
    //


    // Do some generic things across all strategies
    //
}

public function execute(string $param1)
{
    // Do something specific to this method
    //


    // Do some generic things across all strategies
    //
}


public function execute()
{
    // Do something specific to this method
    //


    // Do some generic things across all strategies
}

The all do something very specific but require different parameters for this, then they do something generic that every strategy will do.

Marty Wallace
  • 34,046
  • 53
  • 137
  • 200
  • How do you figure out what the parameters each function needs? Parameter selection has to be part of the strategy, not part of the interface. – Bob Dalgleish Jun 05 '17 at 22:25
  • Is it possible for you to pass in all the required data upon construction of the strategy and remove parameters from the strategy interface? If you can do this then perhaps also move the generic part of the algorithm to an abstract base strategy. Alternatively have your strategy interface expect a package of data (1 model/object) and have the strategy implementations selectively use parts of it. – Reasurria Jun 06 '17 at 07:47

2 Answers2

1

Using the strategy pattern, how can treat different exectute methods differently in terms of them having different parameters?

If you make it work this way, it won't be considered a strategy pattern. The fact that your client knows different strategies require different parameters, invalidates the strategy pattern, because then client is assumed to know (at least partially) what specific strategy does internally.

Understand that strategy should not accept parameters selectively. It should instead work on the parameters selectively. So until you read further down, consider that we now have all strategies accepting all parameters. So that Strategy1 uses only param1 and param2 and ignores param3, and so on.

function execute(param1, param2, param3) { }

However this gets ugly if you have even more parameters. You can instead have a separate Parameter class and pass this collection of parameters to every strategy. Each strategy will include a logic to get and use parameters that it requires and will ignore rest.

then they do something generic that every strategy will do

That's what you can have abstract strategy for. It will include abstract execute() method and it's own execute() method that each concrete strategy will call.

To summarize, here's how it would look like (non-compilable code):

Main()
{
    AbstractStrategy s = new ConcreteStrategy1();
    s.Execute(parameters); // parameters -> collection
}

class AbstractStrategy {
    Execute(parameters); // abstract
    Execute() {} // not public
}

class ConcreteStrategy1 : AbstractStrategy {
    override Execute(parameters) {
        string pvalue1 = parameters.GetValue("param1");
        base.Execute();
    }
}
Nikhil Vartak
  • 5,002
  • 3
  • 26
  • 32
-1

If you require that output of one operation should be used as input to other operation and during this course if number of parameters and their types changes, you can consider following design.

[Pseudo code]

interface IProcess //you can abstract out operations which has common signature here, if //needed

class ProcessOne : IProcess
{
private IProcess nextProcess = new ProcessTwo()
public retVal1 Execute(param1, param2)
{
//ProcessOne Logic
retVal1 retval =  nextProcess.Execute(param1);
return retval;
}
}

Then implement factory to construct chained IProcess types. Get wrapped IProcess instance from factory and call Execute on it. Internally called chained Execute operation on nextProcess instance and cascade output.

Factory enables you to use different implementation of same signature at each level.