Skip to content

Commit 119ad75

Browse files
authored
Update commad pattern
add more clarification
1 parent 393d783 commit 119ad75

File tree

1 file changed

+51
-41
lines changed

1 file changed

+51
-41
lines changed

patterns/behavioral/command.py

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,71 @@
11
"""
2+
Command pattern decouples the object invoking a job from the one who knows
3+
how to do it. As mentioned in the GoF book, a good example is in menu items.
4+
You have a menu that has lots of items. Each item is responsible for doing a
5+
special thing and you want your menu item just call the `execute` method when
6+
it is pressed. To achieve this you implement a command object with the `execute`
7+
method for each menu item and pass to it.
8+
29
*TL;DR
3-
Encapsulates all information needed to perform an action or trigger an event.
10+
Object oriented implementation of callback functions.
411
512
*Examples in Python ecosystem:
613
Django HttpRequest (without `execute` method):
7-
https://docs.djangoproject.com/en/2.1/ref/request-response/#httprequest-objects
14+
https://docs.djangoproject.com/en/2.1/ref/request-response/#httprequest-objects
815
"""
916

10-
import os
1117

18+
class Command:
19+
"""
20+
The interface that commands implement. This is used to abstract invoker from
21+
the command is going to handle the job.
22+
"""
23+
24+
def execute(self):
25+
raise NotImplementedError()
1226

13-
class MoveFileCommand:
14-
def __init__(self, src, dest):
15-
self.src = src
16-
self.dest = dest
27+
28+
class MakeBoldCommand(Command):
29+
"""
30+
A simple command to bold a text.
31+
"""
1732

1833
def execute(self):
19-
self.rename(self.src, self.dest)
34+
print('I am making it bold.')
2035

21-
def undo(self):
22-
self.rename(self.dest, self.src)
2336

24-
def rename(self, src, dest):
25-
print("renaming {} to {}".format(src, dest))
26-
os.rename(src, dest)
37+
class MakeItalicCommand(Command):
38+
"""
39+
A simple command to italic a text.
40+
"""
41+
42+
def execute(self):
43+
print('I am making it italic.')
44+
45+
46+
class MenuItem:
47+
"""
48+
The invoker class. Here it is items in a menu.
49+
"""
50+
51+
def __init__(self, command):
52+
self._command = command
53+
54+
def on_press(self):
55+
self._command.execute()
2756

2857

2958
def main():
3059
"""
31-
>>> from os.path import lexists
32-
33-
>>> command_stack = [
34-
... MoveFileCommand('foo.txt', 'bar.txt'),
35-
... MoveFileCommand('bar.txt', 'baz.txt')
36-
... ]
37-
38-
# Verify that none of the target files exist
39-
>>> assert not lexists("foo.txt")
40-
>>> assert not lexists("bar.txt")
41-
>>> assert not lexists("baz.txt")
42-
43-
# Create empty file
44-
>>> open("foo.txt", "w").close()
45-
46-
# Commands can be executed later on
47-
>>> for cmd in command_stack:
48-
... cmd.execute()
49-
renaming foo.txt to bar.txt
50-
renaming bar.txt to baz.txt
51-
52-
# And can also be undone at will
53-
>>> for cmd in reversed(command_stack):
54-
... cmd.undo()
55-
renaming baz.txt to bar.txt
56-
renaming bar.txt to foo.txt
57-
58-
>>> os.unlink("foo.txt")
60+
>>> item1 = MenuItem(MakeBoldCommand())
61+
62+
>>> item2 = MenuItem(MakeItalicCommand())
63+
64+
>>> item1.on_press()
65+
I am making it bold.
66+
67+
>>> item2.on_press()
68+
I am making it italic.
5969
"""
6070

6171

0 commit comments

Comments
 (0)