cheka.jp 超不定期で更新する写真達。お口直しにどうぞ。

[写経] PHPで学ぶデザインパターン11

— 注意 —
PHPによるデザインパターンの写経ですが、まんま書くと問題があるのでアウトプットとして備忘録メモです

久しぶりのPHP記事です。

Command、要求をクラスで表現

振る舞い + オブジェクト

このパターンは、要求自体をクラスとして表現することで、要求の受付、要求の送信を分離することを実現します。
言葉が難しくて分かり難いですね。

例えば、あるファイルについてバックアップを取得して、特定のファイルのみバックアップ後に削除を行いたいとします。
クラスとして表現できる要求は下記の2つで、要求を送信する側になります。

  • ファイルのバックアップを取得する
  • バックアップ後にファイルを削除する

要求を受け付ける側は、特定のインターフェイスに依存し受け付けた要求を処理します。
インターフェイスに依存させることで処理の中身やメソッド名への依存を排除します。

では具体的にコードを書いて確認してみましょう。

処理の対象となるクラスの作成

コマンドパターンで処理の対象となるクラスです。
今回はファイルが対象となるのでファイルクラスを作成します。

class File{

	//ファイル名保持変数
	private $name;

	//コンストラクタ
	public function __construct($name)
	{
		$this->name = $name;
	}

	//名前の取得
	public function getName()
	{
		return $this->name;
	}

	//バックアップの取得
	public function createBackup()
	{
		print "{$this->name}のバックアップを生成しました\n";
	}

	//バックアップの削除
	public function deleteFile()
	{
		print "{$this->name}を削除しました\n";
	}
}

要求クラスの作成

必要な要求は下記の2つです。
また、要求を受け付けるクラスをインターフェイスに依存させる為に、要求のインターフェイスを定義します。

  • ファイルのバックアップを取得する
  • バックアップ後にファイルを削除する

インターフェイスの生成

/*
コマンドインターフェイス
*/
interface Command{
	public function execute();
}

要求クラスの生成

/*
バックアップ生成コマンドクラス
*/
class CreateBackupCommand implements Command{

	//Fileクラス保持変数
	private $file;

	//コンストラクタ
	public function __construct(File $file)
	{
		$this->file = $file;
	}

	//コマンド実行
	public function execute()
	{
		$this->file->createBackup();
	}
}

/*
ファイル削除コマンドクラス
*/
class DeleteFileCommand implements Command{

	//Fileクラス保持変数
	private $file;

	//コンストラクタ
	public function __construct(File $file)
	{
		$this->file = $file;
	}

	//コマンド実行
	public function execute()
	{
		$this->file->deleteFile();
	}
}

コマンドを受け付けるクラスを作成します。

/*
コマンド保持クラス
*/
class Queue{

	//コマンド保持変数
	private $commands;

	//コンストラクタ
	public function __construct()
	{
		$this->commands = array();
	}

	//コマンド追加
	public function addCommand(Command $command)
	{
		$this->commands[] = $command;
	}

	//コマンドの実行
	public function run()
	{
		foreach ($this->commands as $command) {
			$command->execute();
		}
	}
}

使ってみる

ユーザーCSVとアイテムCSVのバックアップを取得します。
アイテムCSVについてはバックアップ取得後に削除を行います。
*処理は割愛してます

//ユーザーCSVとアイテムCSVを生成する
$userCsv = new File("User.csv");
$itemCsv = new File("Item.csv");

//バックアップコマンドを生成する
$userBackup = new CreateBackupCommand($userCsv);
$itemBackup = new CreateBackupCommand($itemCsv);

//アイテムCSVは削除する
$itemDelete = new DeleteFileCommand($itemCsv);

//コマンドキューに追加
$queue = new Queue();
$queue->addCommand($userBackup);
$queue->addCommand($itemBackup);
$queue->addCommand($itemDelete);

//コマンドを追加
$queue->run();
$php command.php
User.csvのバックアップを生成しました
Item.csvのバックアップを生成しました
Item.csvを削除しました

処理の対象に手を加えずに要求事項を実現出来るパターンが出来上がりました。