Todat I’ll take you to my lab. I’ll show you how to make your code cleaner. Any project can be created by multiple programmers at the same time, and each of them makes more bricks - being forced to understand other people’s bricks. Because you are in my lab, we will start working on real examples - starting with eccomerce, ending with virus treatment!
Strategy Pattern introduction
The strategy pattern next to the factory pattern is one of the most frequently used design patterns. It is easy to understand and to implement. It is one of the behavioral patterns, i.e. those that describe certain behavior. Strategy defines a family of interchangeable algorithms (in the form of classes) that are used to solve the same problem in several different ways.
Implementation
The Context class contains a reference to the StrategyInterface strategy object. The strategy object can be injected by the constructor or setter. The Context class method uses the strategy object to finalize the operation. Strategy classes Strategy1, Strategy2, etc. implement StrategyInterface interface methods. Each of these implementations of StrategyInterface solves a similar problem in a slightly different way. The above diagram can be implemented in the following way:
Before calling the target method, the client selects the injected strategy depending on the condition:
Strategy Pattern Real Life Examples
Let’s get to the practical part. I will show you some examples where Strategy pattern is a perfect solution.
E-commerce - international shipping system with the strategy pattern
Imagine that we own an online shop with many different products. At the beginning, we send products only to the USA, but we want to enter a new market - Europe. We also plan to enter the Australian and African markets. By following the Open/Closed Principle we do not want to add more IFs to our class. In this case, the ideal choice is the strategy pattern!
Let’s start from the Shopping.java interface - responsible for price calculation and currency information.
Now it’s time for some boring model classes: Products.java with our products:
Cart.java class:
Size.java - The price of the products will depend on the size:
Let’s get back to the concrete! It’s time to implement our strategies. Depending on the country of shipping, the relevant customs duty is charged and the shipping cost of EuropeShopping, AmericaShopping increases. Large products (XL-size) have an additional charge.
The above listing shows the calculation of the final price depending on the location of the shipment and product size. Example of use:
Number converter with the strategy pattern
Imagine that you want to create a system to convert numbers into different Numeral Systems . As in the previous example, we will start with the interface:
Time for implementation. We will add support to convert number to octal, binary and hex system:
According to the diagram at the beginning of the post - we will create a class Context that will use our strategies:
An example of how to use a strategy to convert:
Cure the Coronavirus with strategy pattern!
It’s time for something popular :) We will create a strategy to treat viruses. It may seem to you that this is not a very practical use of Strategy Pattern, but imagine a similar situation in any game.
In our case, this could be part of a game taking place in a Hospital For Infectious Diseases! Very often the strategy is used in games to handle movement. We want a player to either walk or run when he moves, but maybe in the future, he should also be able to swim, fly, teleport, burrow underground, etc. Let’s return to the hospital game. Just like before, we start with the interface:
And some implementations:
Now let’s create a class that will work as the Context from the previous point. Let’s name it Treatment.java:
In the above example, we set the strategy through the setter (instead of the constructor). Example of use:
Tax calculation system with the Strategy Pattern
We have a system for creating invoices, but we have customers from different tax zones. What do you think will be the right design pattern? Exactly, the strategy! This time our interface will have one method of calculate():
We’ll need the class responsible for the invoice:
And, as before, the Context class:
Example of use:
The most popular use of the Strategy Pattern in Java
There are a lot of examples to come up with. The most common situations in which the strategy pattern is used are:
Validation: You need to check items according to some rule, but it is not yet clear what that rule will be, and there are likely to be many of them.
Storing information: You want the application to store information to the Database, but later it may be neet to be able to save a file.
Games: as I wrote in previous point - strategy is often used in games, e.g. to correctly handle the movement of objects in games.
Sorting: You want to sort elements, but you do not know what sorting algorithm should you use (BrickSort, QuickSort or other). This is a common case used in examples of Strategy implementation, so I omitted implementation in this article.
Outputting: You need to output text as a plain string, but later may be a CSV, XML or PDF.
Examples of Strategy Pattern in Spring Framework and Java libraries
The strategy is a pattern that you often use using different librarians/frameworks in Java. The best example of the strategy pattern is the Collection.sort() method that takes Comparator parameter. We do not need to change the sort() method to achieve different sorting results. We can just inject different comparators in runtime.
The next example is javax.servlet.Filter#doFilter() method. In Spring Framework an example of using strategy is class: org.springframework.web.servlet.mvc.multiaction.MethodNameResolver
Summary
That’s all about the Strategy Design Pattern🙂 Link to Github with all examples: Github