191 lines
6.2 KiB
Markdown
Raw Normal View History

---
layout: pattern
title: Strategy
folder: strategy
permalink: /patterns/strategy/
categories: Behavioral
language: en
tags:
- Gang of Four
---
## Also known as
2020-09-13 18:15:17 +03:00
Policy
## Intent
2020-09-13 18:15:17 +03:00
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets
the algorithm vary independently from the clients that use it.
2020-07-19 17:34:58 +03:00
## Explanation
Real-world example
2020-07-19 17:34:58 +03:00
> Slaying dragons is a dangerous job. With experience, it becomes easier. Veteran
2020-09-13 18:15:17 +03:00
> dragonslayers have developed different fighting strategies against different types of dragons.
2020-07-19 17:34:58 +03:00
In plain words
> Strategy pattern allows choosing the best-suited algorithm at runtime.
2020-07-19 17:34:58 +03:00
Wikipedia says
2020-09-13 18:15:17 +03:00
> 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.
2020-07-19 17:34:58 +03:00
**Programmatic Example**
Let's first introduce the dragon-slaying strategy interface and its implementations.
2020-07-19 17:34:58 +03:00
```java
@FunctionalInterface
public interface DragonSlayingStrategy {
void execute();
}
@Slf4j
2020-07-19 17:34:58 +03:00
public class MeleeStrategy implements DragonSlayingStrategy {
@Override
public void execute() {
LOGGER.info("With your Excalibur you sever the dragon's head!");
}
}
@Slf4j
2020-07-19 17:34:58 +03:00
public class ProjectileStrategy implements DragonSlayingStrategy {
@Override
public void execute() {
LOGGER.info("You shoot the dragon with the magical crossbow and it falls dead on the ground!");
}
}
@Slf4j
2020-07-19 17:34:58 +03:00
public class SpellStrategy implements DragonSlayingStrategy {
@Override
public void execute() {
LOGGER.info("You cast the spell of disintegration and the dragon vaporizes in a pile of dust!");
}
}
```
And here is the mighty dragonslayer, who can pick his fighting strategy based on the
2020-09-13 18:15:17 +03:00
opponent.
2020-07-19 17:34:58 +03:00
```java
public class DragonSlayer {
private DragonSlayingStrategy strategy;
public DragonSlayer(DragonSlayingStrategy strategy) {
this.strategy = strategy;
}
public void changeStrategy(DragonSlayingStrategy strategy) {
this.strategy = strategy;
}
public void goToBattle() {
strategy.execute();
}
}
```
Finally, here's the dragonslayer in action.
2020-07-19 17:34:58 +03:00
```java
LOGGER.info("Green dragon spotted ahead!");
var dragonSlayer = new DragonSlayer(new MeleeStrategy());
dragonSlayer.goToBattle();
LOGGER.info("Red dragon emerges.");
dragonSlayer.changeStrategy(new ProjectileStrategy());
dragonSlayer.goToBattle();
LOGGER.info("Black dragon lands before you.");
dragonSlayer.changeStrategy(new SpellStrategy());
dragonSlayer.goToBattle();
2020-09-13 18:15:17 +03:00
```
Program output:
```
Green dragon spotted ahead!
With your Excalibur you sever the dragon's head!
Red dragon emerges.
You shoot the dragon with the magical crossbow and it falls dead on the ground!
Black dragon lands before you.
You cast the spell of disintegration and the dragon vaporizes in a pile of dust!
2020-07-19 17:34:58 +03:00
```
What's more, the lambda expressions in Java 8 provides another approach for the implementation:
```java
public class LambdaStrategy {
private static final Logger LOGGER = LoggerFactory.getLogger(LambdaStrategy.class);
public enum Strategy implements DragonSlayingStrategy {
MeleeStrategy(() -> LOGGER.info(
"With your Excalibur you severe the dragon's head!")),
ProjectileStrategy(() -> LOGGER.info(
"You shoot the dragon with the magical crossbow and it falls dead on the ground!")),
SpellStrategy(() -> LOGGER.info(
"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"));
private final DragonSlayingStrategy dragonSlayingStrategy;
Strategy(DragonSlayingStrategy dragonSlayingStrategy) {
this.dragonSlayingStrategy = dragonSlayingStrategy;
}
@Override
public void execute() {
dragonSlayingStrategy.execute();
}
}
}
```
And here's the dragonslayer in action.
```java
LOGGER.info("Green dragon spotted ahead!");
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.MeleeStrategy);
dragonSlayer.goToBattle();
LOGGER.info("Red dragon emerges.");
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.ProjectileStrategy);
dragonSlayer.goToBattle();
LOGGER.info("Black dragon lands before you.");
dragonSlayer.changeStrategy(LambdaStrategy.Strategy.SpellStrategy);
dragonSlayer.goToBattle();
```
The program output is the same as the above one.
## Class diagram
2020-09-13 18:15:17 +03:00
![alt text](./etc/strategy_urm.png "Strategy")
## Applicability
2020-09-13 18:15:17 +03:00
Use the Strategy pattern when
* Many related classes differ only in their behavior. Strategies provide a way to configure a class either one of many behaviors
* You need different variants of an algorithm. for example, you might define algorithms reflecting different space/time trade-offs. Strategies can be used when these variants are implemented as a class hierarchy of algorithms
* An algorithm uses data that clients shouldn't know about. Use the Strategy pattern to avoid exposing complex algorithm-specific data structures
* A class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move the related conditional branches into their own Strategy class
## Tutorial
* [Strategy Pattern Tutorial](https://www.journaldev.com/1754/strategy-design-pattern-in-java-example-tutorial)
## Credits
2020-07-06 13:31:07 +03:00
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)
* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)
* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)
* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)