Addition to the Strategy Pattern
When you read the description of the Strategy Pattern of the GoF book, you come across the paragraph, that the stategy pattern becomes complicated when the number of strategies increases. The explanation is, that the caller of the strategies must know when to apply which concrete strategy.
This can be countered when the you give the responsibility of deciding when to apply a concrete strategy to the strategy itself. In the project I am working at, we came across this point several times. Each time there was a single context object, which could be examined by the stratety objects themselves and then could tell the caller if this strategy is responsible for this context.
This leads to a very straight forward and lean implementation of the caller of the strategies. In combination with a plugin-manager concept (like hivemind in our example) this gets very powerful. You just plug in a new strategy for a newly encountered case and let the strategy decide when this case becomes true. No change in code on the caller side.
Greetings,
Christian
> This can be countered when the you give the> responsibility of deciding when to apply a concrete> strategy to the strategy itself. Unless I'm missing something in your description, GoF refers to this as a "Chain of Command" pattern.
Ok, your approach is based on an important assumption.
- There is enough information available at runtime to decide which is the best strategy to use.
This is rarely obvious to most programmers. For example, say you had various strategies for searching through a list to find duplicates. You could pick the correct strategy each time if you know the distribution of the data, such as if it is sorted, or partially sorted, or totally random. You could have strategies that typically perform better on sorted data than random data, etc.
The idea that you're suggesting is that when you make the programmer pick the strategy, they sometimes mis-judge and use the wrong one.
So you make a trade-off and calculate the best strategy at runtime, given the that a little work to figure out the data distribution will save you big time since you get an algorithm customized for that type of data.
The other side of the trade-off, is that you would need to sample the data quite a bit to figure out how it's distributed, and in that time it might just be faster to apply the a default strategy.
First of all, thank you for your valuable input.
I totally agree with what you say, but I think we assume different things. In your example you assume a situation where each of the available strategies can be applied to deliver a correct result. The difference is merely in time or space consumption.
But in my example (or better in out application) there is a default strategy, but it doesn't deliver corect results in all situations. The concrete problem is an algorith, that let the user navigate via the cursor keys through a user mask. The problem for the strategy is to calculate the next mask element in the direction of the pressed cursor key. This is mostly trivial for the left and right key, but not for up or down. The default strategy is able to calculate those next elements most of the time. But for certain mask elements, this is not trivial and the code would be very ugly, if the default strategy would know every detail of all available mask elements to correctly calculate the next element.
This is the reason why there are special strategies. And for each mask element, that needs special treatment, there is a special strategy. Now it was best practice to let the strategy decide, for which mask element it is responsible.
This is the concrete situation and I thought it would be a nice idea if I would be able to find a new interpretation for the "Strategy pattern".
What do you think?
I think if you can make your code pick the right strategy that's the best way (like what you did).
Maybe when you apply the strategy pattern you could have a strategy pattern chooser that can figure out which strategy to use.
One way to do this is to have your strategy objects implement a chain of responsibility. You would pass the context object to each strategy object and ask it, "are you the best strategy to use?" And the first one that says yes gets to execute. At the end of the chain sits the default strategy which always says yes. However, this requires instantiating all your strategies, which you might not want to do.
Another way to implement it could use a static helper method that takes the context object, examines it, and returns you the correct strategy.
> > This can be countered when the you give the
> > responsibility of deciding when to apply a
> concrete
> > strategy to the strategy itself.
>
> Unless I'm missing something in your description, GoF
> refers to this as a "Chain of Command" pattern.
Yes this is very much like Chain of Responsibity pattern except that it doesent use a chain. I wonder why its not using a chain?
How are you determining which strategy will fill the request, and which ones will not? are you giving them all a chance, or does the first one to fill it somehow disallow the rest from filling it?