コマンドってなに?
要するにコマンド(命令)を統一シグニチャでクラスにまとめて、
一連で実行出来るような仕組みとして実装するパターンです。
身近なところの実装例としては以下
- undo, redo
- エディタのキーボードマクロ(場合によってはスクリプト保存付きも可能)
- キュー管理のバッチジョブコントローラ
コマンドパターンの構造
- Invoker - コマンドをスタックに保持したり、コマンドを実行したり
- Receiver - コマンドに操作される対象のクラス。内部に状態を持っていてCommandの操作によって内部の状態が変化したりする
- Client - Invokerを操作するコントローラ
- Command - 実コマンド。Receiverを操作することでコマンドを実現。Invokerに利用される
<?php
/* Reciever */
class FileSystem {
private $_Path = null;
public function __construct ( $path ) {
$this->_Path = $path;
}
// コマンドに利用されるAPIだよ
public function changeDirectory () {
return `cd $this->_Path`;
}
// コマンドに利用されるAPIだよ。
public function makeDirectory () {
return `mkdir $this->_Path`;
}
// コマンドに利用されるAPIだよ。
public function removeDirectory () {
return `rm $this->_Path`;
}
// コマンドに利用されるAPIだよ。
public function createFile () {
return `touch $this->_Path`;
}
}
<?php
/* command interface */
interface ICommand {
public function execute ();
public function undo ();
}
/* 実コマンド */
class MakeDirectoryCommand implements ICommand {
private $_FileSystem = null;
public function __construct ( $fs ) {
$this->_FileSystem = $fs;
}
public function execute () {
$this->_FileSystem->makeDirectory ();
}
public function undo () {
$this->_FileSystem->removeDirectory ();
}
}
class RemoveDirectoryCommand implements ICommand {
private $_FileSystem = null;
public function __construct ( $fs ) {
$this->_FileSystem = $fs;
}
public function execute () {
$this->_FileSystem->removeDirectory ();
}
public function undo () {
$this->_FileSystem->makeDirectory ();
}
}
<?php
/* Client */
class ShellScript {
private $_Queue = array ();
private $_Position = 0;
public function add ( $cmd ) {
$this->_Queue[] = $cmd;
}
// // MEMO: 実行途中にnextしたり、undoしてポジションを戻して
// // 中途からコマンド上書きしたりも出来るよ
// public function next () {
// return ++$this->_Position;
// }
// public function undo ( $times = 1 ) {
// $this->_Queue[$this->_Position]->undo();
// for ( $i = 0; $times < $i; $i++ ) $this->_Position--;
// }
//
// でも今回はサンプルなのでリニアに実行するだけにするよ
//
public function run () {
foreach ( $this->_Queue as $q ) $q->execute();
}
}
<?php
/* Clientです。クラスじゃないけど */
$sh = new ShellScript();
$fs = new FileSystem ( '/etc/tmp/sample' );
$sh->add ( new MakeDirectoryCommand ( $fs ) );
$sh->add ( new RemoveDirectoryCommand ( $fs ) );
$sh->run ();