BP3 - Command - Learn Design Pattern From Simple Things
As an army commander, you have to plan all the tasks for the soldiers, so that they can execute them. This process is called command.
Command is a behavioral design pattern: 🖤🖤🖤🖤🤍
What is Command?
Command is a technique that object commander is used to encapsulate needed information resource, soldier to execute the task at a later time.
Why use Command?
- Its layout is easy to understand and has good extensibility when more logic comes later.
Question: I hate the Command, what are the alternatives?
Answer: Just code as normal and ignore this pattern, everything in Python is an object, so you can store any object and execute a callback easily.
When to use Command?
Question: When do I use Command?
Answer: When you have a lot of tasks, it is necessary to store and plan for them. Then (maybe after a delay) execute them as planned.
Input:
- Having resources(
Resource for the First Task,Resource for the Main Task,Resource for the Last Task), - Having tasks in order
first_task(NonSoldierCommand.execute),main_task,last_task(SoldierCommand.execute):
# nothing here
Expected Output:
- Resources are appropriately allocated to task, tasks are properly planned first, then it will be executed once the command is activated.
Commander: the first task is:
💣NonSoldierCommand.executing: (Resource for the First Task)
Commander: the main task is:
🧨Commander.executing: (Resource for the Main Task)
Commander: the last task is:
💣SoldierCommand.executing: (<class '__main__.Soldier'>, Resource for the Last Task)
Soldier.do_something with: (Resource for the Last Task)
How to implement Command?
Non-Command implementation:
def non_soldier_command_execute(payload):
print(f" 💣NonSoldierCommand.executing: ({payload})")
def soldier_command_execute(soldier, resource):
print(f" 💣SoldierCommand.executing: ({type(soldier)}, {resource})")
soldier.do_something(resource)
class Soldier:
def do_something(self, resource):
print(f" Soldier.do_something with: ({resource})")
if __name__ == "__main__":
# no planning here, just do everything at once
print("Commander: the first task is:")
non_soldier_command_execute("Resource for the First Task")
print("Commander: the main task is:")
print(f" 🧨Commander.executing: (Resource for the Main Task)")
print("Commander: the last task is:")
soldier = Soldier()
soldier_command_execute(soldier, "Resource for the Last Task")
Command Implementation:
from abc import ABC, abstractmethod
class Command(ABC):
@abstractmethod
def execute(self):
pass
class NonSoldierCommand(Command):
def __init__(self, payload):
self._payload = payload
def execute(self):
print(f" 💣NonSoldierCommand.executing: ({self._payload})")
class SoldierCommand(Command):
def __init__(self, soldier, resource):
self._soldier = soldier
self._resource = resource
def execute(self):
print(f" 💣SoldierCommand.executing: ({type(self._soldier)}, {self._resource})")
self._soldier.do_something(self._resource)
class Soldier:
def do_something(self, resource):
print(f" Soldier.do_something with: ({resource})")
class Commander:
_first_task = None
_last_task = None
def init_first_command(self, command):
self._first_task = command
def init_last_command(self, command):
self._last_task = command
def execute_main_command(self):
print("Commander: the first task is:")
if isinstance(self._first_task, Command):
self._first_task.execute()
print("Commander: the main task is:")
print(f" 🧨Commander.executing: (Resource for the Main Task)")
print("Commander: the last task is:")
if isinstance(self._last_task, Command):
self._last_task.execute()
if __name__ == "__main__":
commander = Commander()
# commander init: a command encapsulating needed information(resource) to execute the task at a later time.
non_soldier_command = NonSoldierCommand("Resource for the First Task")
commander.init_first_command(non_soldier_command)
# commander init: a command encapsulating needed information(soldier, resource) to execute the task at a later time.
soldier = Soldier()
soldier_command = SoldierCommand(soldier, "Resource for the Last Task")
commander.init_last_command(soldier_command)
# after planning, this is the later time, time to execute the tasks initiated by the commander
commander.execute_main_command()
Related posts
-
Verify vs Cert: The Python Requests Handbook
Understanding SSL/TLS in Python Requests: The 'verify' and 'cert' arguments explained with interactive animations.
-
SP7 - Proxy - Learn Design Pattern From Simple Things
The boss wants the employees to focus on work and not get distracted by social media. So he decides to block some websites on the corporate network during working hours.
-
SP6 - Object Pool - Learn Design Pattern From Simple Things
Producing planes on a large scale is expensive, but fortunately the manufactured raw parts are always stored in the pool, thereby reducing duplication in the production process.
-
SP5 - Facade - Learn Design Pattern From Simple Things
There are many departments in the building and you feel confused! By opening the entrances from the facade according to purposes, you simply follow the pre-arranged flow.