Today we start the last of design patterns (in the end !!!), which is called Strategy at reading of this article before someone reaches the bottom of the article to the section "relations with other design patterns" will come to the conclusion that the Strategy pattern is very similar to the State pattern, however, they differ in purpose, but everything in turn :)
Discussion
The main goal of the Strategy pattern is described in the picture below:
I'm joking :)
The main goal the Strategy pattern is to divide many algorithms, encapsulate details of the implementation of these algorithms in derived classes and use them for different situations, later in specific examples it will become more clear :)
The most important elements in implementing this pattern are:
- The Context class, which has a very similar operation as in the State pattern, stores the object of the algorithm class, overwrites it and changes it when we want to act on another algorithm.
- Interface Interface that has defined methods needed for all algorithms.
- ConcreteStrategy classes inheriting from the Interface interface that implement specific algorithms.
You can use the Strategy pattern when you have a lot of algorithms that perform various functions, when is really many of them, it is worth separating them, encapsulating them and using them separately, because later it will probably be hard to use them because they will be tangled with each other.
Let's take an example of functions in the phone, there are so many of these features in some models that it will be best to use the Strategy pattern there to manage and use these functions more easily.
As you can see the Strategy pattern, just like the State pattern, it only makes sense to use it in small and medium projects in small ones, it is unnecessary complications. These patterns, like most patterns, are designed to easier modify the design pattern in the future so that it is clean, flexible and easy to read by everyone.
Intent
- Defining the family of algorithms, encapsulating these algorithms and using them depending on the situation.
- Encapsulate implementation details in derived classes.
Problem
Suppose you have to do a project to save files in various formats, png .txt .csv .jpg etc. the Strategy pattern will be perfect for this, which will separate the algorithms that write files in various formats and encapsulate these algorithms to easier maintain these algorithms in the future.
Use when:
- You have a lot of algorithms entangled with each other performing different functions, then it is better to arrange them, separate them and encapsulate them.
Structure
As usual, the strategy pattern diagram.
It is known in the Discussion section that it was already explained what these classes are doing :) The ImplementationOne and ImplementationTwo classes are concrete ConcreteStrategy classes inheriting from the Interface interface.
And just like in the State pattern, the client operates with specific classes only from the level of the Context class.
Examples
Diagram of the Strategy pattern in code
Let's see now what the Strategy pattern in the code looks like.
Let's start with the Context class.
namespace StrategyPattern
{
class Context
{
private Interface _strategy;
public Context(Interface strategy)
{
_strategy = strategy;
}
public void ContextInterface()
{
_strategy.Algorithm();
}
}
}
As you can see, the class looks very much like the Context class from the State pattern. If we want to use a different algorithm, we will have to pass his object here.
Interface interface now.
namespace StrategyPattern
{
interface Interface
{
void Algorithm();
}
}
And specific classes inheriting from the Interface interface.
Class ImplementationOne.
namespace StrategyPattern
{
class ImplementationOne : Interface
{
public void Algorithm()
{
Console.WriteLine("Called ImplementationOne");
}
}
}
And the ImplementationTwo class.
namespace StrategyPattern
{
class ImplementationTwo : Interface
{
public void Algorithm()
{
Console.WriteLine("Called ImplementationTwo");
}
}
}
And finally the customer.
namespace StrategyPattern
{
class Program
{
static void Main(string[] args)
{
Context context;
context = new Context(new ImplementationOne());
context.ContextInterface();
context = new Context(new ImplementationTwo());
context.ContextInterface();
Console.ReadKey();
}
}
}
It can be seen that the whole structure is very similar to the State pattern, they differ only in the purpose of use.
Result:
Real-life example
The way of transport to the airport
Let's assume that we have to do a system in which the client will be able to decide which way go to the airport, for different ways of transport are fit different algorithms, so it will be good to use the Strategy pattern, see the picture below to show how it looks.
Let's start in the order as in the previous example.
So first, the Context class, in our case it will be called TransportToAirport.
namespace TransportToTheAirport
{
class TransportToAirport
{
private StrategyOfTransport _strategy;
public TransportToAirport(StrategyOfTransport strategy)
{
_strategy = strategy;
}
public void Transport()
{
_strategy.Transport();
}
}
}
The Interface interface in our case will be the abstract class of StrategyOfTransport.
namespace TransportToTheAirport
{
abstract class StrategyOfTransport
{
public abstract void Transport();
}
}
Specific classes inheriting from the StrategyOfTransport class.
So, Car.
namespace TransportToTheAirport
{
class Car : StrategyOfTransport
{
public override void Transport()
{
Console.WriteLine("Client transported by: " + GetType().Name + "\n");
}
}
}
CityBus.
namespace TransportToTheAirport
{
class CityBus : StrategyOfTransport
{
public override void Transport()
{
Console.WriteLine("Client transported by: "+GetType().Name+"\n");
}
}
}
And Taxi.
namespace TransportToTheAirport
{
class Taxi : StrategyOfTransport
{
public override void Transport()
{
Console.WriteLine("Client transported by: " + GetType().Name + "\n");
}
}
}
And the client.
namespace TransportToTheAirport
{
class Program
{
static void Main(string[] args)
{
TransportToAirport transporttoairport;
Console.WriteLine("Client wants to be transported by CityBus");
transporttoairport = new TransportToAirport(new CityBus());
transporttoairport.Transport();
Console.WriteLine("Client wants to be transported by Car");
transporttoairport = new TransportToAirport(new Car());
transporttoairport.Transport();
Console.WriteLine("Client wants to be transported by Taxi");
transporttoairport = new TransportToAirport(new Taxi());
transporttoairport.Transport();
Console.ReadKey();
}
}
}
Result:
And we have the next client :)
Relations with other design patterns
- Implementation of the Strategy pattern is very similar to the State pattern, these patterns differ only in the purpose of use.
- Objects of the Strategy template often use the Flyweight pattern.
- Patterns Strategy, State, Bridge and to some extent Adapter have similar structures, i.e. head (client or handle) and body, only differ in purpose, they are all for different problems
- The Strategy pattern allows you to change the guts of the object and Decorator its skin.
Summary
That’s all about the Strategy :)
Link to github with the whole code from this article: https://github.com/Slaw145/Strategy
This content also you can find on my blog: http://devman.pl/programtech/design-patterns-strategy/
And on medium: https://medium.com/@sawomirkowalski/design-patterns-strategy-2262cfaa2648
That's enough when it comes to design patterns :) Maybe later there will be an additional shorter entry about Null Object. The next topics discussed will likely to develop the subject of Dependency Injection and unit tests :) then it is possible that it will be about CQRS, but we will see :)
And NECESSERILY join the DevmanCommunity community on fb, part of the community is in one place :)
If you recognise it as useful, share it with others so that others can also use it.
Leave upvote and follow and wait for next articles :) .
– site on fb: Devman.pl-Slawomir Kowalski
– group on fb: DevmanCommunity
Ask, comment underneath at the end of the post, share it, rate it, whatever you want :)
Illustrations, pictures and diagrams are from: https://sourcemaking.com/design_patterns/strategy
Hi! I am a robot. I just upvoted you! I found similar content that readers might be interested in:
https://sourcemaking.com/design_patterns/strategy
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Snoop Dogg smokes 81 blunts a day.
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Congratulations @slawas! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Do not miss the last post from @steemitboard:
Vote for @Steemitboard as a witness to get one more award and increased upvotes!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit