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.
What you're talking about is programming to abstractions, which does not imply the Strategy pattern.
Programming to abstractions is always a good practice. There's virtually no additional effort involved in providing an interface or abstract base class for a concrete implementation, and many refactoring tools can now do this automatically for you.
How abstract to make it is a different question.
In your first example, you simply have an abstract type. You could program everything to use a generic Serializer
or ISerializer
type and then wire up a single default implementation in an IoC container like Castle or Spring. Simple. Done.
In the second instance, though, you're designing abstract functionality. You're trying to predict how this abstract type might be used in the future, and you are probably going to be wrong. The YAGNI principle applies here; unless you have some reason to believe that your application actually needs a fully-generic "transform" interface which can turn anything into anything else, and unless you've actually scoped out the requirements for it, then you're wasting your time planning for it. Maybe you should just use one of the many existing XML transformation languages if you need that kind of flexibility.
None of this really has anything to do with the strategy pattern. The strategy pattern means that not only are you coding against an abstract type, but that you are choosing which concrete type to use based on information only known at runtime. This is neither explicit nor implicit in your question.
If you only have one implementation, then implementing a strategy pattern is absolutely overkill, unless you know for sure that you will need to support additional strategies almost immediately afterward.
But that does not preclude you from using abstract types. This is generally how most OO applications are designed now, using dependency injection for code and an IoC container for configuration. I'd go so far as to say this is more productive than coding to concrete types, because (a) it's much easier to test and mock, and (b) quickly coding an interface allows you to continue your current task without much distraction, as opposed to going off and writing a whole new class because you can't continue without it.
So definitely make use of abstract types, but don't overthink things and spend a lot of time fussing about how to generalize them. It's easier to refactor later than it is to work with a bloated interface.
Best Answer
That depends on what you mean by "interface". If you mean the standard general programming meaning of "an abstraction that hides its details" that is used in such words as "User Interface (UI)", "Application Programming Interface (API)", "Application Binary Interface (ABI)", "Network Interface", "Audio Interface" and so on, then yes, it is always an interface. That is, after all, the whole point of the Strategy Pattern.
If you mean the specific Java / C♯
interface
keyword, then no, obviously not, since it doesn't even exist in the overwhelming majority of languages.Strategy.
There is no mention of
interface
on the Strategy Pattern page of the Portland Pattern Repository on Ward's Wiki, nor is there any mention of it in the "Gang of Four Book" (Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, John Vlissides, Ralph Johnson, and Richard Helm).