-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathcommand.py
More file actions
151 lines (110 loc) · 3.53 KB
/
command.py
File metadata and controls
151 lines (110 loc) · 3.53 KB
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
"""
Command Design Pattern
-----------------------
Command Design pattern is a design pattern in which each request is
encapsulated as an object called command. As the command easily capture the
request along with the object and it's method to invoke, we can easily pass
those requests.
Key Components of a command design pattern is as follows:
1. Command Interface: Defines the abstract method `execute` for all concrete commands
2. Concrete Command : A command that implements Command Interface
3. Receiver : An object that performs the operation
4. Invoker : An object that stores and executes commands
5. Client : An object that configures command objects
One of the popular usecase of the command design pattern is game development.
We can encapsulate the behavior of different objects with the single command and
each operations can be invoked using `execute()` method.
"""
from abc import ABC, abstractmethod
from enum import Enum
class Command(ABC):
"""
This is a Command Interface that defines the blueprint for concrete command.
"""
@abstractmethod
def execute(self):
pass
class Player:
def run(self):
print("Player Running")
def jump(self):
print("Player Jumping")
class Tank:
def move(self):
print("Tank Moving")
def fire(self):
print("Tank Firing")
class PlayerRunCommand(Command):
"""
This is a concrete command that implements the Command Interface.
"""
def __init__(self, player: Player) -> None:
self.player = player
def execute(self):
self.player.run()
class PlayerJumpCommand(Command):
def __init__(self, player: Player) -> None:
self.player = player
def execute(self):
self.player.jump()
class TankMoveCommand(Command):
def __init__(self, tank: Tank) -> None:
self.tank = tank
def execute(self):
self.tank.move()
class TankFireCommand(Command):
def __init__(self, tank: Tank) -> None:
self.tank = tank
def execute(self):
self.tank.fire()
class Keys(Enum):
UP = 1
SPACE = 2
class Controller:
"""
This is an invoker that stores and executes command on `key_press`
"""
def __init__(self, commands: dict[Keys, Command]) -> None:
self.commands = commands
def key_press(self, key: Keys):
command = self.commands.get(key)
"""
The command object here is a receiver that run command
"""
if command:
print(f"[ {key:^10s} ]: ", end="")
command.execute()
if __name__ == "__main__":
player = Player()
tank = Tank()
"""
Here, player_controller and tank_controller are clients that creates and
configures command objects
"""
player_controller = Controller(
{
Keys.UP: PlayerRunCommand(player),
Keys.SPACE: PlayerJumpCommand(player),
}
)
tank_controller = Controller(
{
Keys.UP: TankMoveCommand(tank),
Keys.SPACE: TankFireCommand(tank),
}
)
print("[ Player Active ]".center(40, "="))
player_controller.key_press(Keys.UP) # command is invoked
player_controller.key_press(Keys.SPACE)
print("[ Tank Active ]".center(40, "="))
tank_controller.key_press(Keys.UP)
tank_controller.key_press(Keys.SPACE)
"""
OUTPUT:
===========[ Player Active ]============
[ Keys.UP ]: Player Running
[ Keys.SPACE ]: Player Jumping
============[ Tank Active ]=============
[ Keys.UP ]: Tank Moving
[ Keys.SPACE ]: Tank Firing
"""