Reputation: 68770
The template method pattern and the strategy pattern do roughly the same thing. I understand the basic differences between them (template method is inheritance based, strategy is composition based), but are there any decent guidelines on when to choose one over the other? It seems like they do basically the same thing.
Upvotes: 34
Views: 16880
Reputation: 30652
The two can actually be used together quite effectively.
Here's a video that details how
Don't think of patterns as recipes with specific code to implement them.
It's the design intent that is the key, and there can be many implementations. By mentioning a pattern name in your code somewhere, you're letting a reader in on your intent when you wrote that code. The implementation is secondary.
Template method gives you an "algorithm with replaceable steps". (The algorithm is normally defined in a non-overridable method (final or private for example) )
The GoF implementation of this concept uses inheritance and method overriding to replace those steps.
However, you're still using Template method if those steps are replaced by strategies.
For example, think about a class that wants to walk a binary tree inorder and "do something" at each node.
The intent is that the inorder() method is a template method - the structure of the walk is always the same.
The "hook" method, the part that "does something" can be implemented as a method in the same class (and overridden in subclasses to change behavior), or externally, in which case it's a strategy for "doing something".
Upvotes: 22
Reputation: 83
I think the answer from @Lennaert is correct. I would like to add some details to it:
The Template pattern differs from the Strategy pattern in a sense that the Template Method uses inheritance and the Strategy pattern uses composition to achieve a common goal. The Strategy pattern is preferred in case the strategies/algorithms are ‘self-contained’ (e.g. more then just a difference in a ‘simple’ return) and must be shared amongst possible other clients/Contexts. The Template pattern is preferred in case the algorithms diverge in their fine details (e.g. just a difference in a ‘simple’ return) and/or access of the internal details of the concrete implementation is required by the base class.
This means:
Upvotes: 0
Reputation: 1037
My summary: The Strategy Pattern is more loosely coupled than the Template Method pattern, which is generally a good thing.
Robert C. Martin in TEMPLATE METHOD & STRATEGY: Inheritance vs. Delegation
Thus, the STRATEGY pattern provides one extra benefit over the TEMPLATE METHOD pattern. Whereas the TEMPLATE METHOD pattern allows a generic algorithm to manipulate many possible detailed implementations, by fully conforming to the DIP the STRATEGY pattern additionally allows each detailed implementation to be manipulated by many different generic algorithms.
DIP is the Dependency Inversion Principle:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions.
Upvotes: 2
Reputation: 173
I would prefer using a mix of both, dumping default implementation (from Template pattern) into Context class of strategy pattern. This way, I can enforce user to call method I want them to call so that the order of execution on algorithm's steps remains controlled.
/**
* enables replaceable steps in algorithm
*/
public interface HouseStrategy{
void buildWalls();
void buildPillars();
}
public class HouseContext{
//public API that enforces order of execution
public void build(HouseStrategy strategy){
buildFoundation();//default implementation
strategy.buildPillars();//delegated to concrete strategy
strategy.buildWalls();//delegated to concrete strategy
buildWindows();//default implementation
}
//default implementation
private void buildWindows() {
System.out.println("Building Glass Windows");
}
//default implementation
private void buildFoundation() {
System.out.println("Building foundation with cement,iron rods and sand");
}
}
public class WoodenHouse implements HouseStrategy {
@Override
public void buildWalls() {
System.out.println("Building Wooden Walls");
}
@Override
public void buildPillars() {
System.out.println("Building Pillars with Wood coating");
}
}
public class GlassHouse implements HouseStrategy {
@Override
public void buildWalls() {
System.out.println("Building Wooden Of glass");
}
@Override
public void buildPillars() {
System.out.println("Building Pillars with glass coating");
}
}
As we can see, concrete strategies are still open to extension. As in,
public class GlassHouse implements HouseStrategy,EarthquakeResistantHouseStrategy{......}
The usage
HouseContext context = new HouseContext();
WoodenHouse woodenHouseStrategy = new WoodenHouse();
context.build(woodenHouseStrategy);
GlassHouse glassHouseStrategy = new GlassHouse();
context.build(glassHouseStrategy);
One disadvantage I see here is that concrete strategies can only change the variant behavior of algorithm i.e. buildWalls() and buildPillars(). If we need to change invariant parts i.e. buildFoundation() and buildWindows(), we need to make another Context class implementing the new behavior. Still, we get some code reusability which is not found in pure Strategy Pattern :-)
Upvotes: -1
Reputation: 23
I would almost always go for strategy for the very important reason that client code has no dependency on implementation whereas in template pattern part of implementation stays in the abstract class and any change in abstract class may need to change the client which very often result in rigid code and we end up developer telling that "this came out to be a bigger change than I expected".
But in cases when it is really helpful to get common code in an abstract class I would not hesitate to do it and also try to keep code related to client code away from it
Upvotes: 1
Reputation: 272
I disagree with this statement (from this answer):
"Template method is specifically targeted at cases where you want people to be able to inherit from your class and want them to be able to override your implementation in a controlled manner."
If you WANT people to inherit from your class then you're WANTING a specific implementation, rather than wanting a particular behaviour. That smells bad to me.
A valid thing to WANT is the ability to override or provide implementations of individual steps of an algorithm. That goal can be achieved by both Template Methods (where we can selectively override protected methods) or the Strategy Pattern (where we inject implementations).
If you are building a class that implements an algorithm, and you want to allow steps in that algorithm to be altered by other developers, that's your requirement. Your only decision is whether to allow them to do that via inheritance or composition.
All other things being equal we should favour composition over inheritance, but we should only even get to the inheritance/composition decision by first figuring out what our goal is (we may need neither).
I would never start with "I want to allow them to inherit from this class". That's cart before the horse IMO.
Upvotes: 8
Reputation: 698
I would like to agree and second Scott's explanation.
Template pattern = cares about drawing the generic lines along which an operation will be carried on - templating - basically an "algorithm with replaceable steps" (very well coined) where the replaceable steps can be delegated using the Strategy pattern concept.
Strategy pattern = cares only about decoupling the client from the underlining implementation of an operation whose outcome needs to always abide by some predetermined rules (like sorting where the outcome is always a sorted list but you may deffer de actual sorting to bubble sort or to quick sort).
Cheers.
Upvotes: 4
Reputation: 2465
I use Template method when the algorithm needs knowledge of the internals of the objects it runs on.
In all other cases (i.e. when the algorithm only needs to use the object's interface), I try to use Strategy.
Further, Strategy is only useful when there are actual algorithms to implement: If the only difference between classes is (for example) what simple value to return, use Template method.
Upvotes: 21
Reputation: 1019
Consider usage strategy when:
In other cases it should be enought to use template pattern.
Upvotes: 14
Reputation: 59912
You can create big inheritance tree just to change one of the N behavior. And you can create second big inheritance tree to change second of the N behavior.
But also you can unload your tree by creating small strategy trees.
So if you noticed that you add more and more classes just to add some changes in some behavior - it is time to supply your classes with strategies.
Upvotes: 5
Reputation: 7501
Strategy allows for a reusable algorithm to be used in more than one place. If you have an algorithm that can be provided by your consumer and can be used in several places, this is a good spot for Strategy (sorting algorithms, predicates, comparers... are good examples of that).
Template method is specifically targeted at cases where you want people to be able to inherit from your class and want them to be able to override your implementation in a controlled manner (basically preventing them from replacing all your plumbing and offering them a specific extension point without risking a problem because they did not call the base method or called it at the wrong time).
They can be similar, and they can serve the same kind of purpose depending on what you are actually doing. As with all design patterns, it is difficult to answer such a question because there is not really a definitive answer. It's actually easier to decide in context...
Upvotes: 39
Reputation: 300769
One of the central OO Design principles is "Favour Composition over Inheritance", so that suggests to favour the Strategy pattern. It obviously depends on what you are trying to accomplish in a particular scenario.
Upvotes: 3