views:

62

answers:

2

In Refactoring to Patterns the author replaces the conditional logic by having the client use Loan factory methods where each uses the appropriate Strategy for the given arguments. However, I feel like it has passed the conditional logic code to the client, which must choose based on the arguments which Loan factory method to call. Isn't that moving rather than replacing?

The DP book hammers on the same illusion:

For example, without strategies, the code for breaking text into lines could look like

void Composition::Repair () {
    switch (_breakingStrategy) {
    case SimpleStrategy:
        ComposeWithSimpleCompositor();
        break;
    case TeXStrategy:
        ComposeWithTeXCompositor();
        break;
    // ...
    }
    // merge results with existing composition, if necessary
}

The Strategy pattern eliminates this case statement by delegating the linebreaking task to a Strategy object:

void Composition::Repair () {
    _compositor->Compose();
    // merge results with existing composition, if necessary
}

Yes, but how does one choose from which Strategy class to instantiate compositor? Conditional logic? I see that if the context had a hieararcy, then the conditional logic would be even farther away, since each subclass could instantiate the appropriate Strategy, but that would have also applied to Composition::repair() where each subclass would directly call ComposeWithSimpleCompositor instead of ComposeWithTeXCompositor.

A: 

This is the case which you can't escape.

Your client is the only entity in your system who knows which strategey to choose and you really can't avoid.

We implement Strategy Pattern to avoid conditional logic in client class so that these classes should be closed for modification. for e.g. you are writing a TaxCalculator Module and Tax calculation algorithms are Country specific i.e. in US there is a different logic and in UK that is different so you don't want your TaxCalculator directly implement these logic in a function because if you add one more country , you need to modify your TaxCalculator. So for changing different implementation at runtime , you need a specific dependency ( or you can say Startgey) and you need to inject this dependency at runtime.

and to indenify correct dependency or startgey , you must have some Factory method or Service Locator which can inject your dependency.

You are not moving Conditional logic to another class rather you are injecting stratgey at runtime by using Factory method.

saurabh
You blurred the problem in general statements. The conditional logic to choose which strategy is going to be moved to the client, is not it? Isn't that what you call 'the case you can't escape'?
simpatico
"The conditional logic to choose which strategy is going to be moved to the client, is not it?" No i havn't blurred your question but shows you that for changing stratgey at runtime , you need a place in your code where you decide which stratgey to choose and my whole point is to move this choosing appropiate stratgey object must not be in the class which is using startgey object.
saurabh
+2  A: 

Yes - choice of a design pattern sometimes moves logic rather than replacing it.

I don't really understand your objection though. Some of the decision logic is already in the client, and strategy consolidates the decision.

In your code sample

void Composition::Repair () {
    switch (_breakingStrategy) {
    case SimpleStrategy:
        ComposeWithSimpleCompositor();
        break;
    case TeXStrategy:
        ComposeWithTeXCompositor();
        break;
    // ...
    }
    // merge results with existing composition, if necessary
}

the _breakingStrategy field will have to have been supplied somewhere, presumably by the client code determining which composition method to use and passing the result of that decision as the value of _breakingStrategy.

The only thing applying Strategy is doing is making that decision supply a Strategy subclass instead of a "type code" as it is now, consolidating the decision.

The decision does of course have to be made somewhere. If you feel the Composition::Repair method is the right place for it, you are of course free to not use a Strategy pattern at all.

If you want to use Strategy but you don't want the logic in the client (any more than it already is), a Factory Method containing a similar switch could supply it.

Don Roby