デザインパターン-Command

Commandパターンとは

Commandパターンとは、命令・操作をクラス(オブジェクト)で表現し、オブジェクトを切り替えることで操作の切り替えを実現するパターンです。

1つ以上の命令を1つのオブジェクトで表現して、命令の詳細処理をカプセル化します。

「Command」とは「命令」を意味します。


Commandパターンの利点

  • 命令をオブジェクトとして管理するため、その命令の履歴管理、UNDO(取消し)機能の実装等が容易に行えます。
    • Commandクラスに実行したコマンド結果を保持しておくことで、Undo機能やRedo機能を実現することができます。
  • 処理をクラスとして独立させることで、再利用性を高めることが出来る。
    • 命令そのものが独立したクラスとして実装されますので、他のアプリケーションでの再利用がしやすくなります。
  • 処理のキューイング
    • 要求と実際の実行を別のタイミングで実施することができるようになります。

構成要素

  • Command(命令)
    • 命令のインタフェースを定義します。
  • ConcreteCommand(具体的な命令)
    • 「Command」のインタフェースを実装します。
  • Receiver(受信者)
    • 「Command」の処理対象となるオブジェクトのインタフェースです。
  • ConcreteReceiver(具体的な受信者)
    • 「Receiver」のインタフェースを実装します。
  • Invoker(起動者)
    • 「Command」で定義されているインタフェースを呼出します。
  • Client(利用者)

rubyによるCommandパターンの実装


#!/usr/bin/env ruby

# Command(命令) のインタフェースを定義します。
class Command
  attr_reader :description
  def initialize(description)
    @description = description
  end
  
  # 特定の何かをするための命令
  def execute
  end
end

# ConcreteCommand(具体的な命令) 
class CreateFile < Command
  def initialize(path)
    super("Create file : #{path}")
    @path = path
  end
  
  def execute
    f = File.open(@path, "w")
    f.close
  end
end

# ConcreteCommand(具体的な命令) 
class DeleteFile < Command
  def initialize(path)
    super("Delete file : #{path}")
    @path = path
  end
  
  def execute
    File.delete(@path)
  end
end

# Invoker(起動者) 
class CompositCommand < Command
  def initialize
    @commands = []
  end
  
  def append(cmd)
    @commands << cmd
  end
  
  def execute
    @commands.each { |cmd| cmd.execute }
  end
  
  def description
    puts("実行コマンドは設定されていません。") if(@commands.empty?)
    @commands.each { |cmd| puts(cmd.description) }
  end

  # 最後の命令を削除
  def undo
    @commands.pop if(!@commands.empty?)
  end

  def clear
    @commands.clear
  end
end

cmds = CompositCommand.new
cmds.append(CreateFile.new("file1.txt"))
cmds.append(DeleteFile.new("file1.txt"))
cmds.description
cmds.execute

関連ページ