DEV Community

Cover image for What You Need To Know About The Helpful Strategy Pattern

What You Need To Know About The Helpful Strategy Pattern

Kyle Galbraith on January 29, 2018

I have recently been revisiting various coding patterns while learning new languages. One pattern that is a personal favorite of mine is the strate...
Collapse
 
risingsungames profile image
James • Edited

Nice article.

Apologies if this is obvious, but I like to use reflection to find classes implementing ITextExtractor followed by Activator.CreateInstance to instantiate them and add them to the array at runtime, thereby reducing the steps needed in adding a new implementation to just step 1 in your list above - "Add the new text extraction class".

Of course, this is only useful if the order of the items in the array isn't important!

Collapse
 
kylegalbraith profile image
Kyle Galbraith

James that is a slick idea. I would like to see a demo of that with some code so that I can wrap my head around it further. Thank you for the comments.

Collapse
 
risingsungames profile image
James

Sure! Might not be suitable for a group project, it makes assumptions that all ITextExtractor classes have parameterless constructors which isn't immediately obvious and wouldn't go down well in my employers code reviews, but for personal projects I find it useful! Something along the lines of this:

private ITextExtractor[] _extractors;

public RunExtraction()
{
    _extractors =  AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(x => x.GetTypes())
        .Where(t => typeof(ITextExtractor).IsAssignableFrom(t) && !t.IsInterface)
        .Select(t => (ITextExtractor)Activator.CreateInstance(t))
        .ToArray();
}
Collapse
 
brunobck profile image
Bruno

Great post sir, I have some points though.
At run time the "ifs and elses" and "_extractors.FirstOrDefault(e => e.UseExtractor(fileExtension));" aproach would have not differences, right? Because all the latter line does, is to get the first "extrator" that first satisfies the condition by doing "ifs and elses" as well...
I think your code would take more advantage of interfaces if it was like this:

public string[] Extract(string filePath, ITextExtractor extractor)
{
    if(extractor != null)
    {
        return extractor.ExtractContent(filePath);
    }
    else
    {
        throw new Exception("unable to extract content");
    }
}

To decide at run time what Strategy to use, you might use some parameterized Factory Method.
Let me know what you think please.

Collapse
 
kylegalbraith profile image
Kyle Galbraith

This could certainly work but it loses the benefit of abstracting out the extractors. The idea is that each extractor knows what it can extract and it indicates that with the function that finds it.

This provides nice encapsulation by allowing the class that implements the interface to decide what it can extract.

Your idea would be quite different and more akin to the Factory pattern.

Collapse
 
greenfieldcoder profile image
Jimmy

I might overuse this pattern, but I love working with it!

Tip: Use an IOC to setup all the ITextExtractors on startup and you dont have to worry about missing a step when adding another ITextExtractor

Collapse
 
sambenskin profile image
Sam Benskin

Great explanation, short and to the point. Always good to get refreshers on design patterns.