The strategy pattern is one of the first patterns I learned, and it leads into at least one other pattern that I used constantly! Let’s do this thing!
I’ve not been having as much time to focus on writing as I’d like, so I figured I’d try to knock out some pattern review for myself while hopefully working on more significant posts in the background. The first post in this potential series of posts - The strategy pattern!
The strategy pattern
In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.
from Wikipedia
What does that mean? Well to me, it’s just having multiple implementations of a single interface. That’s it. One of the first things I think about when it comes to the strategy pattern, is having multiple “Provider” implementations for something like logging.
Implementation
public interface ILogger
{
void Log(string message);
}
That’s our interface. There’s not much to the contract. We have a method called Log
which expects a string
message.
So how does this get utilized as a “strategy”? Multiple implementations!
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
public class FileLogger : ILogger
{
public void Log(string message)
{
// Gonna have to use our imagination here...
var currentColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(message);
Console.ForegroundColor = currentColor;
}
}
(Note, don’t use that file logger, it’s terrible… In fact! don’t use any of it, it’s just an example!)
static void Main(string[] args)
{
ILogger logger = null;
logger = new ConsoleLogger();
logger.Log($"Doot doot, this should be a {nameof(ConsoleLogger)}. {logger.GetType()}");
logger = new FileLogger();
logger.Log($"Doot doot, this should be a {nameof(FileLogger)}. {logger.GetType()}");
}
Reasons to use this pattern
What does the use of this pattern buy us?
- Writing code to the abstraction that is
ILogger
rather than a concrete implementation - making Unit testing easier. - Select an algorithm implementation at run time, perhaps based on a user’s input, or configuration.
- Ties into other patterns, one of my favorites being the “Factory” (TODO write about a factory).
Note that I got some pushback in a programming slack group that the above is not in fact an example of the strategy pattern, due to not having selected the implementation at run time (since I did it in code at compile time). I disagree, but wanted to throw that out there cuz I’ve been wrong before! :D
The code for this pattern can be found on my pattern repo: https://github.com/Kritner-Blogs/Kritner.PatternExamples
Resources:
Top comments (2)
Strategy may be my favorite design pattern. I usually feel pretty good about the places where I used it, as compared to...like, "Builder" which is the one I probably misuse the most.
OOOOoooooh man I love me some builder pattern. There are some pretty fancy things you can do with them!
Maybe that'll be next after I finish the TODO factory ;)