Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've started looking into Design Patterns recently, and one thing I'm coding would suit the Strategy pattern perfectly, except for one small difference.

Essentially, some (but not all) of my algorithms, need an extra parameter or two passed to them.

So I'll either need to

  • pass them an extra parameter when I invoke their calculate method

or

  • store them as variables inside the ConcreteAlgorithm class, and be able to update them before I call the algorithm.

Is there a design pattern for this need / How could I implement this while sticking to the Strategy Pattern?

I've considered passing the client object to all the algorithms, and storing the variables in there, then using that only when the particular algorithm needs it. However, I think this is both unwieldy, and defeats the point of the strategy pattern.

Just to be clear I'm implementing in Java, and so don't have the luxury of optional parameters (which would solve this nicely).

share|improve this question
    
Optional parameters like in C++ would solve nothing, as they're just a shorthand for defining multiple overloaded methods. –  maaartinus Mar 13 '11 at 15:20
    
I'd try hard to avoid storing the additional parameters somewhere where I had to change them before use. This way you make ConcreteAlgorithm stateful, so it can't be passed easily to other method or threads. Moreover, it's too easy to forget to set the parameters. –  maaartinus Mar 13 '11 at 16:39
add comment

5 Answers 5

Samuel, is it possible to encapsulate the parameter that each of the strategies take into one common class and then extend that common Parameter class to add more behavior that some of your strategies specifically need?

E.g.

StrategyParameter //Base strategy parameter that most of the strategies need
        ^
        |
        |
SpecialStrategyParameter // will be used for strategies that need more parameter

And then, define strategy hierarchy like:

Interface MyStrategy {
   void myStrategyMethod(StrategyParameter parameter);
}

class MyNormalStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

call the above strategy as: myNormalStrategyInstance.myStrategyMethod(strategyParameter);

class MySpecializedStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

call the above strategy by passing SpecialStrategyParameter instance instead like: mySpecializedStrategy.myStrategyMethod(specialStrategyParameter);

Please update if something is not clear. Will be happy to explain/clarify.

share|improve this answer
    
-1 requires downcast, breaks encapsulation of design. Though it is an improvement on the design in the question, there are better ways to skin this cat. –  tallseth Aug 7 '13 at 12:34
add comment

You need to clarify your strategy.

It all depends on how you use your algorithms. For your client class to use different strategy implementations interchangeably, they all need to have a common abstraction. If they don't follow the same interface, maybe what you need are different abstractions.

I've used configurable strategies before, where you parameterize the concrete classes on construction:

interface Strategy {
  int calculate();
}

class ConcreteStrategyThatNeedsAParameter implements Strategy {
  private final int param;
  public ConcreteStrategyThatNeedsAParameter(int param) {
    this.param = param;
  }
  public int calculate() { 
    // uses param...
  }
}

Now, someone still needs to create an instance of this class and pass it to your client. But your client still only needs to know about the Strategy interface.

It also works if your strategy method takes parameters, but then your client knows about those parameters and passes them to all implementations it works with.

share|improve this answer
add comment

As long as the signature is defined on the interface clearly, it still complies with the Strategy pattern.

The patterns as written are the absolute most simple form that still exhibits the behaviour expected, so you can embellish them as long as you keep the original intent. That of course is assuming you want to follow the pattern. There's no point using a pattern if it doesn't fit, or just because it's there, but in your case I think you're fine.

share|improve this answer
add comment

extending on the above answer provided by peakit - you can use abstraction. I am using peakit's code here -

Interface MyStrategy { abstract void myStrategyMethod(StrategyParameter parameter); }

class MyNormalStrategy extends MyStrategy { public override void myStrategyMethod(StrategyParameter parameter) { //implement the logic here } }

class MySpecializedStrategy extends MyStrategy { public override void myStrategyMethod(StrategyParameter parameter, ExtraStrategyParameter extraParameter) { //implement the logic here } }

If i understand your question correctly you wanted to pass an extra parameter to certain algorithms right ? Please let me know if this is what you were looking for ?

share|improve this answer
add comment

If you look into the Design patterns book, it isn't wrong per se that some SimpleStrategy exists that uses less or none of the passed parameters, or that the parameters are a one-size-fits-all/least-common-multiplier. The design choice here is whether this hurts you in terms of extra processing that ends up not being used.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.