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

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

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

初心者には分かりやすくて良い本なので、是非本屋でチェックして下さい。

URL: http://www.amazon.co.jp/PHPによるデザインパターン入門-下岡-秀幸/dp/4798015164
PHPによるデザインパターン入門

AbstractFactoryで関連する部品を生成する

生成 + オブジェクト

[写経] PHPで学ぶデザインパターン04で登場したFactory Methodと似たパターンですが、明確な違いはFactoryを生成するところです。
ロジックはほぼ同じなので過去の記事が理解できれば難しく無いと思います。

システム構築時によく使うパターンとしてモックを準備する場面を想定して進めてみます。

API設計だけ完了して未実装のクラスとテスト用のモックを準備する

/*
Daoクラス
*/
class Dao {
	//シングルトン用のインスタンス
	private static $instance;
	//コンストラクタ
	private function __construct() {
	}
	//複製を禁止する(継承されてもエラーにするようにfinalで宣言する)
	public final function __clone() {
		throw new RuntimeException ("複製したらダメだよ!!");
	}
	//シングルトンの取得
	public static function getInstance() {
		if(!isset(self::$instance)){
			self::$instance = new self();
		}
		return self::$instance;
	}
	//保存処理
	public function save($data) {
		print "まだ実装中です!\n";
		print "ID:{$data["id"]},TITLE:{$data["title"]}\n";
		return false;
	}
}

テスト用のクラスも準備します。

/*
テスト用のDaoクラス
*/
class DaoMock {
	//シングルトン用のインスタンス
	private static $instance;
	//コンストラクタ
	private function __construct() {
	}
	//複製を禁止する(継承されてもエラーにするようにfinalで宣言する)
	public final function __clone() {
		throw new RuntimeException ("複製したらダメだよ!!");
	}
	//シングルトンの取得
	public static function getInstance() {
		if(!isset(self::$instance)){
			self::$instance = new self();
		}
		return self::$instance;
	}
	//保存処理
	public function save($data) {
		print "テストクラスです!\n";
		print "ID:{$data["id"]},TITLE:{$data["title"]}\n";
		return true;
	}
}

Factoryを生成するクラスとインターフェイスを準備します

/*
AbstractFactoryを準備する
*/
interface AbstractFactory {
	public function createDao();
}

本番時に利用されるFactory

/*
本番で利用されるFactory
*/
class DaoFactory implements AbstractFactory {
	public function createDao(){
		return Dao::getInstance();
	}
}

テスト時に利用されるFactory

/*
モックとして利用されるFactory
*/
class DbMockFactory implements AbstractFactory {
	public function createDao(){
		return DaoMock::getInstance();
	}
}

モックを利用してみる

/*
利用してみる
*/
//テスト中のコード
$factory = new DbMockFactory();
$dao = $factory->createDao();
$dao->save(array("id"=>1,"title"=>"テスト保存ですよ!"));

結果確認

テストクラスです!
ID:1,TITLE:テスト保存ですよ!

本番クラスを利用してみる

/*
利用してみる
*/
//テスト中のコード
$factory = new DaoFactory();
$dao = $factory->createDao();
$dao->save(array("id"=>1,"title"=>"テスト保存ですよ!"));

結果確認

まだ実装中です!
ID:1,TITLE:テスト保存ですよ!

Factoryクラスのメソッドが1つなのでFactory Methodとの違いがあまり出ていませんが、3個、4個と生成する部品が増えた場合にFactoryで分離する事でテストが楽になるパターンです。
個人的に気をつけているポイントは、Factoryに複雑なロジックを構築せず関連はあくまで生成されるクラス内にて行うように心掛けています。