Strategy is a behavioral design pattern:
š¤š¤š¤š¤š¤
What is Strategy?
Strategy is a technique to be able to insert a new logic/plugin TikiTaka, CounterAttack
into a main object FootballClub
dynamically.
Why use Strategy?
- Defining new logic/plugin will not change the code of the main object.
- The new logic/plugin will only be plugged in as needed, make the code more comprehensible.
Question: I hate the Strategy, what are the alternatives?
Answer: You can create multiple logic/plugins counter_attack_pass_the_ball
, tiki_taka_pass_the_ball
directly in main object instead of Plugins, but it’s not pretty!
When to use Strategy?
Question: When do I use Strategy?
Answer: When you have multiple logic/plugins TikiTaka, CounterAttack
for an object and logic/plugins usage changes over time.
- Having a main object
FootballClub
:
- There is a main feature
attack
with multiple logic/plugins TikiTaka, CounterAttack
being swapped out for each situation š.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
"""
class FootballClub:
def attack(self):
formation = [
["LB", "CB", "CB", "CB"],
["LCM", "CDM", "RCM"],
["LW", "CF", "RW"],
]
...pass_the_ball...
"""
import random
from abc import ABC, abstractmethod
class Strategy(ABC):
name = ""
@abstractmethod
def pass_the_ball(self, formation):
pass
class TikiTaka(Strategy):
name = "TikiTaka"
def pass_the_ball(self, formation):
defenders = formation[0]
midfielder_forwards = [*formation[1], *formation[2]]
random.shuffle(defenders)
random.shuffle(midfielder_forwards)
return [*defenders, *midfielder_forwards]
class CounterAttack(Strategy):
name = "CounterAttack"
def pass_the_ball(self, formation):
defenders = random.choice(formation[0])
midfielders = random.choice(formation[1])
forwards = random.choice(formation[2])
return [defenders, midfielders, forwards]
|
Expected Output:
- The main object
FootballClub
has the ability to dynamically run different pass_the_ball
logic/plugins at different times:
- at the start:
pass_the_ball
in CounterAttack style.
- at the end:
pass_the_ball
in TikiTaka style.
1
2
3
4
|
Manager: Hey team! apply CounterAttack
LB >> CDM >> RW >> GOAAAALLL!!!
Manager: Hey team! apply TikiTaka
CB >> CB >> LB >> CB >> CDM >> RCM >> RW >> LW >> LCM >> CF >> GOAAAALLL!!!
|
How to implement Strategy?
Non-Strategy implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
class FootballClub:
def __init__(self, strategy):
self._strategy = strategy
@property
def strategy(self):
return self._strategy
@strategy.setter
def strategy(self, strategy):
self._strategy = strategy
def attack(self):
formation = [
["LB", "CB", "CB", "CB"],
["LCM", "CDM", "RCM"],
["LW", "CF", "RW"],
]
result = []
if self._strategy == "TikiTaka":
result = self.tiki_taka_pass_the_ball(formation)
elif self._strategy == "CounterAttack":
result = self.counter_attack_pass_the_ball(formation)
result.append("GOAAAALLL!!!")
print(" >> ".join(result))
def tiki_taka_pass_the_ball(self, formation):
defenders = formation[0]
midfielder_forwards = [*formation[1], *formation[2]]
random.shuffle(defenders)
random.shuffle(midfielder_forwards)
return [*defenders, *midfielder_forwards]
def counter_attack_pass_the_ball(self, formation):
defenders = random.choice(formation[0])
midfielders = random.choice(formation[1])
forwards = random.choice(formation[2])
return [defenders, midfielders, forwards]
if __name__ == "__main__":
strategy = "CounterAttack"
football_club = FootballClub(strategy)
print(f"Manager: Hey team! apply {strategy}")
football_club.attack()
strategy = "TikiTaka"
print(f"Manager: Hey team! apply {strategy}")
football_club.strategy = strategy
football_club.attack()
|
Strategy Implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
class FootballClub:
def __init__(self, strategy):
self._strategy = strategy
@property
def strategy(self):
return self._strategy
@strategy.setter
def strategy(self, strategy):
self._strategy = strategy
def attack(self):
formation = [
["LB", "CB", "CB", "CB"],
["LCM", "CDM", "RCM"],
["LW", "CF", "RW"],
]
result = self._strategy.pass_the_ball(formation)
result.append("GOAAAALLL!!!")
print(" >> ".join(result))
if __name__ == "__main__":
strategy = CounterAttack()
football_club = FootballClub(strategy)
print(f"Manager: Hey team! apply {strategy.name}")
football_club.attack()
strategy = TikiTaka()
print(f"Manager: Hey team! apply {strategy.name}")
football_club.strategy = strategy
football_club.attack()
|
Source Code