I’m trying to understand the strategy pattern and asking myself: is the context class must-have or can I leave it out without compromising pattern’s purpose ?
I was under the impression I needed some kind of switch for reading different types of files but didn’t want to just hack something and later deal with refactoring (although, of course it always happens that code can be refactored but the idea was: try to be as smart as possible in the design beforehand…):
Image taken from wikimedia
Can the client delegate directly to the Strategy interface or is there something I just missed to understand about the context class?
interface Reader {
// read information from file and fill data list field of Client
readFile();
}
class ExcelReader implements Reader{ /* */ }
class PdfReader implements Reader{ /* */}
class Client{
// strategic choice
Reader r;
// data list field
List<Data> data;
// Client Constructor
public Client(){
if(<file ends in .xls>)
r = new ExcelReader();
else
r = new PdfReader();
r.readFile();
}
}
So, above depicted is the context class missing. Does the code adhere to the strategy pattern?
3
In your example, the code calling readFile
is part of the Client constructor. That method is the “context” you are looking for. The strategy pattern does not need a “context class” literally, and at the first version of your code the strategy object (the “Reader” in your case) may reside just in a local variable. Especially when there is just one “strategic method” (“readFile”) to be called.
However, if your codebase grows from one version to the next, it is not unlikely getting more and more “strategic” methods to be called, and the decision which strategy to apply and the performing of the “strategic methods” will happen at different times and at different places in your code. So you start to refactor them to keep the logic in one place. This will lead straightforward to an implementation looking similar to the diagram in your question.
0
Certainly. Patterns are just guidelines. You will still need to adapt and apply them correctly for the problem at hand. Personally, I rarely ever allow the strategy to be set at runtime; more often it is specified on construction or spun up in a factory.
Though it could also be argued that setStrategy
is private and my injection is just using the pattern as shown.
2