6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Pythonで、デザインパターン「Command」を学ぶ

Last updated at Posted at 2020-01-26

GoFのデザインパターンをPythonで学習してみたいと思います。

■ Command(コマンド・パターン)

Command パターン(英: command pattern)はオブジェクト指向プログラミングにおけるデザインパターンの一つで、動作を表現するオブジェクトを示す。Command オブジェクトは、動作とそれに伴うパラメータをカプセル化したものである。
例として、印刷を行うライブラリが PrintJob クラスを備えているとする。ライブラリのユーザーは新たに PrintJob オブジェクトを作成し、パラメータ(印刷するドキュメント、印刷部数など)をセットし、最後にプリンターにジョブを送信するメソッドを呼び出す。

UML class and sequence diagram

W3sDesign_Command_Design_Pattern_UML.jpg

UML class diagram

command.png
(以上、ウィキペディア(Wikipedia)より引用)

■ "Command"のサンプルプログラム

実際に、Commandパターンを活用したサンプルプログラムを動かしてみて、次のような動作の様子を確認したいと思います。

  • ファイル権限"777"のtest1.txtファイルを作成する
  • ファイル権限"600"のtest2.txtファイルを作成する

なお、サンプルプログラムは、第一引数:作成したいファイル名、第二引数:付与したいファイル権限とします。

$ 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

ファイル一覧を確認します。

$ 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

想定どおり、ファイルが生成できました。

■ サンプルプログラムの詳細

Gitリポジトリにも、同様のコードをアップしています。
https://github.com/ttsubo/study_of_design_pattern/tree/master/Command

  • ディレクトリ構成
.
├── Main.py
└── command
    └── command.py

(1) Command(命令)の役

命令のインタフェースを定める役です。
サンプルプログラムでは、Commandクラスが、この役を努めます。

command/command.py
from abc import ABCMeta, abstractmethod

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

    @abstractmethod
    def display(self):
        pass

(2) ConcreteCommand(具体的命令)の役

Command役のインタフェースを実際に実装している役です。
サンプルプログラムでは、FileTouchCommandクラスと ChmodCommandクラスが、この役を努めます。

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) Receiver(受信者)の役

ConcreteCommand役の命令を実行するときに対象となる役です。命令の受け取り手と呼んでもよいでしょう。
サンプルプログラムでは、FileOperatorクラスが、この役を努めます。

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) Invoker(起動者)の役

命令の実行を開始する役です。Command役で定義されているインタフェースを呼び出す役になります。
サンプルプログラムでは、CompositeCommandクラスが、この役を努めます。

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) Client(依頼人)の役

ConcreteCommand役を生成し、その際にReceiver役を割り当てる役です。
サンプルプログラムでは、startMainメソッドが、この役を努めます。

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))

■ 参考URL

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?