[GO] Learn the design pattern "Command" in Python

I would like to learn GoF design patterns in Python.

■ Command (command pattern)

The Command pattern (English: command pattern) is one of the design patterns in object-oriented programming, and indicates an object that expresses an action. The Command object is an encapsulation of the behavior and its associated parameters. As an example, suppose the library that prints has the PrintJob class. The library user creates a new PrintJob object, sets the parameters (document to print, number of copies, etc.), and finally calls the method to send the job to the printer.

UML class and sequence diagram W3sDesign_Command_Design_Pattern_UML.jpg UML class diagram command.png (The above is quoted from Wikipedia)

■ "Command" sample program

Actually, I would like to try running a sample program that utilizes the Command pattern and check the following behavior.

--Create a test1.txt file with file permission" 777 " --Create a test2.txt file with file permissions" 600 "

In the sample program, the first argument is the file name you want to create, and the second argument is the file authority you want to grant.

$ python Main.py test1.txt 777
% touch test1.txt
% chmod 777 test1.txt
$ python Main.py test2.txt 600
% touch test2.txt
% chmod 600 test2.txt

Check the file list.

$ ls -l|grep test
-rwxrwxrwx  1 ttsubo  staff    0  1 26 13:01 test1.txt
-rw-------  1 ttsubo  staff    0  1 26 13:01 test2.txt

As expected, the file was generated.

■ Details of sample program

Similar code has been uploaded to the Git repository. https://github.com/ttsubo/study_of_design_pattern/tree/master/Command

--Directory structure

.
├── Main.py
└── command
    └── command.py

(1) The role of Command

It is the role that determines the interface of instructions. In the sample program, the Command class serves this role.

command/command.py


from abc import ABCMeta, abstractmethod

class Command(metaclass=ABCMeta):
    @abstractmethod
    def execute(self):
        pass

    @abstractmethod
    def display(self):
        pass

(2) The role of ConcreteCommand

This is the role that actually implements the interface for the role of Command. In the sample program, the FileTouchCommand and ChmodCommand classes serve this role.

command/command.py


class FileTouchCommand(Command):
    def __init__(self, filename, receiverObj):
        self.__filename = filename
        self.__receiver = receiverObj

    def execute(self):
        self.__receiver.createFile(self.__filename)

    def display(self):
        print("% touch {0}".format(self.__filename))


class ChmodCommand(Command):
    def __init__(self, filename, permission, receiverObj):
        self.__filename = filename
        self.__permission = permission
        self.__receiver = receiverObj

    def execute(self):
        self.__receiver.changeFileMode(self.__filename, self.__permission)

    def display(self):
        permission = format(self.__permission, 'o')
        print("% chmod {0} {1}".format(permission, self.__filename))

(3) The role of Receiver

This is the target role when executing the command of the ConcreteCommand role. You may call it the recipient of the order. In the sample program, the FileOperator class serves this role.

command/command.py


from pathlib import Path

...(snip)

class FileOperator(object):
    def createFile(self, filename):
        Path(filename).touch()

    def changeFileMode(self, filename, permission):
        Path(filename).chmod(permission)

(4) The role of Invoker

It is the role that starts the execution of the instruction. It serves to call the interface defined by the Command role. In the sample program, the CompositeCommand class serves this role.

command/command.py


class CompositeCommand(Command):
    def __init__(self):
        self.__cmds = []

    def append_cmd(self, cmd):
        self.__cmds.append(cmd)

    def execute(self):
        for cmd in self.__cmds:
            cmd.execute()
    
    def display(self):
        for cmd in self.__cmds:
            cmd.display()

(5) The role of Client

This is the role that creates the ConcreteCommand role and assigns the Receiver role at that time. In the sample program, the startMain method serves this role.

Main.py


import sys
from command.command import FileOperator, CompositeCommand, FileTouchCommand, ChmodCommand


def startMain(filename, permission):
    recv = FileOperator()
    cc = CompositeCommand()
    cc.append_cmd(FileTouchCommand(filename, recv))
    cc.append_cmd(ChmodCommand(filename, permission, recv))
    cc.execute()
    cc.display()


if __name__ == "__main__":
    startMain(sys.argv[1], int(sys.argv[2], 8))

■ Reference URL

-Implementing the Command pattern in Python -Design pattern in Python ~ Py design pattern ~ / Command pattern

Recommended Posts

Learn the design pattern "Command" in Python
Learn the design pattern "Builder" in Python
Learn the design pattern "Flyweight" in Python
Learn the design pattern "Observer" in Python
Learn the design pattern "Memento" in Python
Learn the design pattern "Proxy" in Python
Learn the design pattern "Visitor" in Python
Learn the design pattern "Bridge" in Python
Learn the design pattern "Mediator" in Python
Learn the design pattern "Decorator" in Python
Learn the design pattern "Iterator" in Python
Learn the design pattern "Strategy" in Python
Learn the design pattern "Composite" in Python
Learn the design pattern "State" in Python
Learn the design pattern "Adapter" in Python
Learn the design pattern "Abstract Factory" in Python
Learn the design pattern "Template Method" in Python
Learn the design pattern "Factory Method" in Python
Learn the design pattern "Chain of Responsibility" in Python
Learn the design pattern "Singleton" with Python
Learn the design pattern "Facade" with Python
In the python command python points to python3.8
Implement the Singleton pattern in Python
Singleton pattern in Python
Visitor pattern in Python
Download the file in Python
Find the difference in Python
Execute external command in python
Learn cumulative sum in Python
Design Patterns in Python: Introduction
Learn exploration in Python # 1 Full exploration
External command execution in Python
Python Design Pattern --Template method
Getting the arXiv API in Python
Hit a command in Python (Windows)
Save the binary file in Python
Hit the Sesami API in Python
Run shell command / python in R
Get the desktop path in Python
Get the script path in Python
Have python read the command output
Hit the web API in Python
I wrote the queue in Python
Calculate the previous month in Python
Examine the object's class in python
Get the desktop path in Python
Get the host name in Python
Access the Twitter API in Python
The first step in Python Matplotlib
I wrote the stack in Python
Command for the current directory Python
Master the weakref module in Python
Learn the basics of Python ① Beginners
python Note: Determine if command line arguments are in the list
Load the remote Python SDK in IntelliJ
Try using the Wunderlist API in Python
Check the behavior of destructor in Python
[Python Kivy] About changing the design theme
Try using the Kraken API in Python
[LLDB] Create your own command in Python
Learn the basics while touching python Variables