問題
特定のシステムへの要求を効果的に表現する必要がありますが、要求の性質や処理方法の知識はありません。
説明
「チーム」テンプレートを使用するには、少なくとも3つの動機があります。
- 後続のロギング/ロギングなどのために、オブジェクトの形式でリクエストをカプセル化します
- 「オブジェクトのメソッドを呼び出す」という本質に、独立したオブジェクトのプロパティを付与する。
- オブジェクト指向のコールバック(コールバック);
実際、上記の動機はすべて1つに集約されます- 「要求をオブジェクトとしてカプセル化する」 。 そのようなアプローチが効果的で正当化される多くのタイプのシステムが知られています。 まず、ユーザーアクション(取り消し/やり直し)をキャンセルして繰り返す機能を備えた、それほど深刻ではないデスクトップアプリケーションです。 第二に、これらは、いくつかの操作を初期化する主要なプリミティブとしてオブジェクトの形式のクエリを使用するネットワーク分散システムです。 第三に、コールバックオブジェクトの形式でコールバックをカプセル化する非同期呼び出しをサポートするシステム。 無限にリストできますが、コマンドテンプレートは最も一般的なテンプレートの1つであり、OOPの形成の段階で文字通り登場し、その後GoFブックで正式に記述されたことを理解することが重要です。
テンプレートの基本的な考え方は、単一のインターフェースを使用して、システムで実行できるすべてのタイプの操作を記述することです。 次に、サポートシステムに新しい操作を追加するには、提案されたインターフェイスを実装するだけで十分です。 したがって、各操作は、追加のプロパティの特定のセットをカプセル化する独立したオブジェクトのように見えます。 システムは、要求(オブジェクト)に対して追加のアクションセットを実行する機能を取得します。 これは、ロギング、前のアクションの取り消し、次のアクションの繰り返しなどです。
実用例
テンプレートを使用する最も明白な動機-ロギング/やり直しを考慮してください。 このために、それがあったと想像してください、<皮肉>
Stephen Bourne(bashの著者)がGoFの本を読み、「チーム」デザインパターンが何であるかを知っていた場合</ sarcasm>
。 およそ次のようになります。
- シェル内の各コマンドは、個別のクラス(Commandクラスの子孫)にカプセル化されます。
- コマンドシェルはロギング/ロギングメカニズムをサポートし、最も重要なことは、ユーザーアクションの取り消し/やり直し、つまり チーム;
既存のソリューションの設計における問題を変更し、コマンドをキャンセルして繰り返す機能を備えた自転車を書きます。
この目標を達成するには、実行されたコマンドのキューの概念を導入するだけで十分です。コマンド(オブジェクト、コマンドの後続)は実行後に取得され、キャンセルされたコマンドのキューにはキャンセルされたコマンドが到着します。 さらに、チームアクションを実行およびキャンセルするための個別のメカニズムが必要です。 明らかに、これらのメカニズムは各チームごとに異なります。 次に、全体的なシステムを実装するために、2つのキューを使用して、対応するアクションを最上位にあるオブジェクト(実行またはキャンセル)に適用するだけで十分です。
クラス図
シェルがサポートする各コマンドは、コマンドクラスを拡張する必要がありますが、3つのメソッド(execute()、cancel()、およびname())を実装する必要があります。
シェルクラスは、説明のみを目的として示されています。 上記の実装では、main()メソッドがそれを置き換えます。
Pythonの実装
# -*- coding: cp1251 -*- from sys import stdout as console # exit class SessionClosed(Exception): def __init__(self, value): self.value = value # class Command: def execute(self): raise NotImplementedError() def cancel(self): raise NotImplementedError() def name(): raise NotImplementedError() # rm class RmCommand(Command): def execute(self): console.write("You are executed \"rm\" command\n") def cancel(self): console.write("You are canceled \"rm\" command\n") def name(self): return "rm" # uptime class UptimeCommand(Command): def execute(self): console.write("You are executed \"uptime\" command\n") def cancel(self): console.write("You are canceled \"uptime\" command\n") def name(self): return "uptime" # undo class UndoCommand(Command): def execute(self): try: cmd = HISTORY.pop() TRASH.append(cmd) console.write("Undo command \"{0}\"\n".format(cmd.name())) cmd.cancel() except IndexError: console.write("ERROR: HISTORY is empty\n") def name(self): return "undo" # redo class RedoCommand(Command): def execute(self): try: cmd = TRASH.pop() HISTORY.append(cmd) console.write("Redo command \"{0}\"\n".format(cmd.name())) cmd.execute() except IndexError: console.write("ERROR: TRASH is empty\n") def name(self): return "redo" # history class HistoryCommand(Command): def execute(self): i = 0 for cmd in HISTORY: console.write("{0}: {1}\n".format(i, cmd.name())) i = i + 1 def name(self): print "history" # exit class ExitCommand(Command): def execute(self): raise SessionClosed("Good bay!") def name(self): return "exit" # COMMANDS = {'rm': RmCommand(), 'uptime': UptimeCommand(), 'undo': UndoCommand(), 'redo': RedoCommand(), 'history': HistoryCommand(), 'exit': ExitCommand()} HISTORY = list() TRASH = list() # def main(): try: while True: console.flush() console.write("pysh >> ") cmd = raw_input() try: command = COMMANDS[cmd] command.execute() if not isinstance(command, UndoCommand) and not isinstance(command, RedoCommand) and not isinstance(command, HistoryCommand): TRASH = list() HISTORY.append(command) except KeyError: console.write("ERROR: Command \"%s\" not found\n" % cmd) except SessionClosed as e: console.write(e.value) if __name__ == "__main__": main()
使用する
$ python pysh.py pysh >> rm You are executed "rm" command pysh >> rm You are executed "rm" command pysh >> rm You are executed "rm" command pysh >> history 0: rm 1: rm 2: rm pysh >> undo Undo command "rm" You are canceled "rm" command pysh >> exit Good bay!
ご注意
一部のソースでは、テンプレートはActionまたはTransactionと呼ばれます。