[写経] PHPで学ぶデザインパターン14
|— 注意 —
PHPによるデザインパターンの写経ですが、まんま書くと問題があるのでアウトプットとして備忘録メモです
GWボケに負けないように一気に進めてしまいます。
Flyweight、同じものは一度しか作らない
構造 + クラス、オブジェクト
状況によって変化しない情報を表現するクラスのインスタンス化を1度にし、利用するオブジェクト間で共有するためのパターンです。
生成されるオブジェクトの数を最小にしてリソースの消費を抑えることが可能になります。
再利用されるクラス
状況によって変化しない情報を表現するクラスです。
/* 商品クラス */ class Item { private $code; private $name; private $price; //コンストラクタ public function __construct($code,$name,$price) { $this->code = $code; $this->name = $name; $this->price = $price; } //コードを取得 public function getCode() { return $this->code; } //名前を取得 public function getName() { return $this->name; } //価格を取得 public function getPrice() { return $this->price; } }
再利用するためのファクトリークラス
商品一覧をプールするためのクラスです。
/* 商品をカプセル化して再利用する為のクラス */ class ItemFactory { private $pool; private static $instance = null; //コンストラクタ public function __construct($data) { $this->buildPool($data); } //シングルトンオブジェクトを生成する public static function GetInstance($data) { if(is_null(self::$instance)) { self::$instance = new ItemFactory($data); } return self::$instance; } //カプセル化した商品インスタンスから該当するデータを取得する public function getItem($code) { if(array_key_exists($code,$this->pool)) { return $this->pool[$code]; } else { return null; } } //商品一覧を生成する private function buildPool($data) { $this->pool = array(); //改行で区切ってリストを生成する $lists = explode("\n",$data); foreach ($lists as $row) { list($item_code,$item_name,$item_price) = explode("\t",$row); $this->pool[$item_code] = new Item($item_code,$item_name,$item_price); } } //複製を許可しない public final function __clone() { throw new RuntimeException('複製できません!'.get_class($this)); } }
使ってみる
通常はDBやファイルから生成すると思いますが、ハードコーディングで商品一覧を準備しています。
$data = "001 商品1 100\n"; $data .= "002 商品2 200\n"; $data .= "003 商品3 400\n"; $data .= "004 商品4 800"; $factory = ItemFactory::GetInstance($data); //商品1を取得する $item1 = $factory->getItem("001"); print_r($item1); //商品2を比べてみる $item2 = $factory->getItem("002"); if($item2 == $factory->getItem("002")) { print "同一オブジェクト002\n"; }
$php flyweight.php
Item Object ( [code:Item:private] => 001 [name:Item:private] => 商品1 [price:Item:private] => 100 ) 同一オブジェクト002
同一オブジェクトが再利用されているのが分かると思います。
データの量が多い場合に有効なパターンなので、ちゃんと使いこなしたいパターンですね!