Question

I am new to design patterns and working my way through the Factory Method and Strategy patterns. I understand that Factory is a creational pattern and Strategy is behavioral but I struggle to understand when to use which one. For example, I have the following classes that updates client details based on the company specified:

    public interface IUpdateDetails { void UpdateDetails(); }

    public class UPSUpdateDetails : IUpdateDetails
    {
        public void UpdateDetails() => Console.WriteLine("Call web service to update details for UPS...");
    }

    public class FedExUpdateDetails : IUpdateDetails
    {
        public void UpdateDetails() => Console.WriteLine("Update database for FedEx...");
    }

    public class DHLUpdateDetails : IUpdateDetails
    {
        public void UpdateDetails() => Console.WriteLine("Send Email for DHL...");
    }

I can create a Factory to return the correct class:

    public class UpdateDetailsFactory
    {
        public static IUpdateDetails Create(string type)
        {
            switch (type)
            {
                case "UPS":
                    return new UPSUpdateDetails();
                case "DHL":
                    return new DHLUpdateDetails();
                case "FedEx":
                    return new FedExUpdateDetails();
                default:
                    throw new ArgumentException();
            }
        }
    }

and implement it as follows:

    // Using Factory
    string company = "UPS"; // Get company from database
    IUpdateDetails updateDetails = UpdateDetailsFactory.Create(company);
    updateDetails.UpdateDetails();
    Console.ReadLine();

or I can use the Strategy pattern:

    public class UpdateDetailsContext
    {
        private IUpdateDetails strategy;

        public void SetStrategy(IUpdateDetails updateDetails) => strategy = updateDetails;

        public void Update() => strategy.UpdateDetails();
    }

and implement it as follows:

    // Using Strategy
    UpdateDetailsContext context = new UpdateDetailsContext();
    context.SetStrategy(UpdateDetailsFactory.Create(company));
    context.Update();
    Console.ReadLine();

My question is - am I understanding the patterns correctly? What is the difference between using the one over the other?

Was it helpful?

Solution

You are correct that these have a lot of similarities. As mentioned in other answers, the difference is about goals.

The Strategy pattern is often misunderstood but it's also one of them most valuable patterns for simplifying code. The key to the pattern is that it allows you to have objects that change their behavior at runtime. To think of a good example of this, consider a video game where you are in some sort of battle with a non-player enemy. At some point, when you have reduced the enemy's 'health' to a certain level, the enemy will change from a 'fight' to a 'flight' mode. Now, you could put a bazillion if statements all over the place to check which mode it's in but that's a huge mess. Instead, you use a strategy pattern and have a set of different behavior definitions represented as objects. Depending on the 'health' level, the correct behavior is used.

This doesn't just apply to video games. Let's say you have an ordering system and you've been given requirements to fall back to a secondary cloud provider (more expensive but more reliable, let's say.) You could use the strategy pattern to keep that sane.

The factory method pattern is a nice replacement for a constructor. A great example of this is something like an Integer factory that returns the same object every time you pass in the value 0 or 1.

The thing is that you can actually put these together in lots of interesting ways. For example, you could create a factory method that uses a strategy pattern to determine what objects to create. For example, you might use it in the above ordering system example to return a different DB connection objects depending on the circumstances.

A common saw is "patterns are descriptive, not prescriptive." In other words, these are ways to describe a design approach, not recipes. A common mistake is trying to use them like legos to build a solution.

OTHER TIPS

My question is - am I understanding the patterns correctly?

Mostly. Your factory implementation, while correct, is a little odd because the only difference is UpdateDetails. This sort of thing would be better done as a strategy (a simple lambda in C#). In practice, factories tend to vary their concrete implementations a bit more - making the difference in the patterns more clear.

What is the difference between using the one over the other?

In general, a strategy is used by other objects. You give them the strategy, and they do it without knowing necessarily what it does. You use them when you want to make your behavior flexible.

A Factory provides you with some unknown object based on runtime inputs. You use them when you want to vary your result at runtime. Usually though, you have a fixed set of things the factory can build. You're not looking for flexibility as much as you're looking to abstract away conditional creation.

And remember that patterns are mostly for communication. Even if you can accomplish the same things with a strategy and factory pattern, they imply different things when you communicate to other developers. Factory is clearly "I am creating some stuff" where a strategy is slightly less clearly "I am letting you specify some behavior".

When you have more than one pattern that fits a problem well, the primary differences between the patterns is how you envision consuming them. Often patterns don't live in isolation and are used with other design principles that influence whether one is more preferable to the other.

For example, the Factory Pattern as you've defined it is perfectly fine for ensuring you have the correct version of the IUpdateDetails implementation. Dependency Injection based applications typically implement the factory for you so that it can automatically wire the correct implementation when you actually need to consume it. There are some cases where you would actually need to have the factory as you've defined it as well.

When the use case is simple (as in your provided example), there isn't any benefit of the strategy pattern. It's just a bit more work for no additional benefit. However, if we were to expand the example a lot more, we would see it's value a bit more.

Let's now start fleshing this out:

class ShippingContext
{
    private IUpdateDetails updateDetails;
    private IQueryHistory queryHistory;
    private string trackingNumber;
    private string currentLocation;

    public ShippingContext(string trackingNumber)
    {
        this.trackingNumber = trackingNumber;

        var company = ShippingFactory.DetectCompany(trackingNumber);
        queryHistory = ShippingFactory.CreateHistoryTracker(company);
        updateDetails = ShippingFactory.CreateDetailsUpdater(company);
    }

    public TrackingHistory RetrieveHistory()
    {
        var history = queryHistory.Retrieve(trackingNumber);
        lastLocation = history.Current.Location;

        return history;
    }

    public void UpdateDetails()
    {
        updateDetails.Update(trackingNumber, lastLocation);
    }
}

In this case we hide away all the details of the several classes we are using, and how to coordinate them. All that's exposed is the fact we are doing the same work against a known tracking number.

var context = new ShippingContext("1Z9999999999999999");

var history = context.RetrieveHistory();
// do some extra things with history, or display it on screen
context.UpdateDetails();

Console.ReadLine();

The thing that the Strategy Pattern provides is the step-by-step process on how to interact with things. The details as to what needs to happen under the covers is taken care of on the user's behalf.

am I understanding the patterns correctly?

Yes. I would say your implementations look theoretically perfect.

What is the difference between using the one over the other?

You might as well say none...

But

Let me tell you a "secret":

  • Code represents knowledge.

As a result, your code should be a narrative of what you have in your mind. The technical details will be written, eventually, but they will be hidden as deep out of sight as possible.

Whatever you can do with the strategy pattern, you can do with the factory pattern as well (and many other patterns). Your choice should be guided by the following rule of thumb:

  • Use whichever looks less weird!

And by "less weird", I mean, of course, whatever best matches your modeled reality (i.e. your narrative). We choose to write code in the most expressive way possible because this is how we understand it better. This is how patterns emerged... by translating real-world ideas to code. Therefore, they way to choose between patterns is to think about which one would express your problem more intuitively.

So... UpdateDetails is a class (OK, hidden behind an interface). It represents an object. What is the meaning of such an object? The way I read it, it reminds me more of an action than an object, in a natural language narrative (because it is a verb). I am already confused from your representation of an action as an object, so a factory only complicates things further. This means that if you use a factory, you are not clear in your narrative anymore.

Therefore, to answer your question more directly, you use a Factory when:

  • You have an object-like concept in mind (think noun), and you want to vary (abstract away) the way it is created.

You use a Strategy when:

  • You have an action-like concept in mind (think verb), and you want to vary (abstract away) the way it is performed.

All this, not because of some "high-above" rule, but because you make your code a "narrative" of a real-life situation, so more people will be able to interpret it (including your future self, when you get back to your own code and try to remember what you intended to do), thus increasing its expressiveness!

The Factory pattern is intended to be used when creating instances of types that implement a specific interface of interest (i.e when creating something that does implement the interface you need). The Factory pattern hides all the unnecessary details of how the interface implementation was created, hence, allowing to be changed later on as needed without (or almost without) affecting the rest of the code that actually uses the "thing" implementing the interface. Actual Factory could be either parameterless or parameterized depending if the interface implementation creation logic needs some "hints" on how exactly to create the implementation instance.

The Strategy pattern is intended to allow an easy alternation of an expected action/operation implementation as needed. Each alternative is implemented by different relevant strategy types implementing the "similar" action/operation. On the other hand, a Factory implementation usually assumes that the same factory can produce alternative implementations of the expected/requested interface (based on some conditions, parameters, pre-configuration).

Both patterns can be used together in more complex scenarios where, for example, a Factory uses a collection of Strategies internally in order to delegate actual construction of the expected interface implementation object to a specific Strategy after the Factory made a decision with Strategy should be actually used. But this way the called of the Factory has no idea that the Strategies are invoked behind the scene.

This switch case could be changed by polymorphism (as described in Martin Fowler book) .

In order to attend polymorphism, you can use abstract factory, which in each concrete factory inheriting from it, will contain the respective logic.

The class itself doesn't need to know which factory will comes from the constructor, it can be "UPS" , "NHL" or any other, since it inherits from IFactory.

Licensed under: CC-BY-SA with attribution
scroll top