今日の出来事
- 仕事した
- Abstract Factory パターンをPHPで書いてみた。
所感
Abstract Factory パターンをPHPで書いた
最近、めっちゃこれにハマってる。
めっちゃ丁寧に言語化されてて分かりやすい。
まあ、長いこと デザインパターンを正しく学んでなかった僕なので・・・一回ちゃんと学ぼうという事でマンガで紹介されてる場面を例にしてコードに落とし込んで見る事にした。
という事で 一日目はこちら Abstract Factory パターン。
題材はラジコンだけどモーターとかタイヤとか色々登場させると煩雑になっていやになるので、
- ユーザー(作る人)
- ラジコンの同梱パック Factory(リモコンとラジコン が入った箱)
- リモコン
- ラジコン本体
こんな構成にした。
各部品の実装
まずは リモコン と ラジコン 本体の interface を切る
ラジコンの抽象クラスでは、前進・後退の命令を受信した時の振る舞いを持たせた。
/* ラジコンの抽象クラス */ interface RadioControlCarInterface { public function forward(); public function back(); }
続いて、リモコンの抽象クラスでは、どのラジコンと対応するかという依存と、前進・後退の命令を送信する時の振る舞いをもたせた。
/* リモコンの抽象クラス */
interface RemoteControllerInterface
{
/**
* @return RadioControlCarInterface
*/
public function get_relate_radio_control_car();
public function send_forward();
public function send_back();
}
各部品の抽象クラスの実装
続いて それらの抽象クラスから 具象クラスを作る。 例えば タカラトミー のラジコンを買ってきた場合とかを想定してみた。
抽象クラスに沿って ラジコンを具象クラスにした
class TakaraTommyRadioControlCar implements RadioControlCarInterface { public function forward() { echo "前進! \r\n"; } public function back() { echo "後退! \r\n"; } }
抽象クラスにそって リモコンも具象クラスにした。 ちゃんと、タカラトミーのリモコンにしか 信号を送信しないようにしている。
class TakaraTommyRemoteController implements RemoteControllerInterface { /** * @return TakaraTommyRadioControlCar */ public function get_relate_radio_control_car() { return new TakaraTommyRadioControlCar(); } public function send_forward() { $this->get_relate_radio_control_car()->forward(); } public function send_back() { $this->get_relate_radio_control_car()->back(); } }
リモコン・ラジコン をセットにする Factory を定義
ということで リモコンとラジコンが出来た。 続いてこれらを組み合わせる。
interface RadioControllerFactoryInterface { /** * @return RemoteControllerInterface */ public function get_remote_controller(); /** * @return RadioControlCarInterface */ public function get_radio_control_car(); } class TakaraTommyRadioControllerFactory implements RadioControllerFactoryInterface { public function get_remote_controller() { return new TakaraTommyRemoteController(); } public function get_radio_control_car() { return new TakaraTommyRadioControlCar(); } }
これがいわゆる リモコン・ラジコン の対にして、生成をしてくれる Abstract Factory の部分という認識をした。
使用者の実装
最後に ユーザーに使ってもらう。 まず、ラジコンを遊ぶ Userクラスを定義した。
class User { /** @var RadioControllerFactoryInterface */ private $radicon_facotry; public function __construct($radicon_facotry) { $this->radicon_facotry = $radicon_facotry; } public function play() { /* 前進 */ $this->radicon_facotry->get_remote_controller()->send_forward(); /* 後退 */ $this->radicon_facotry->get_remote_controller()->send_back(); } }
実際に呼び出してみる。
$takara_tommy_radicon_facotry = new TakaraTommyRadioControllerFactory();
$user = new User($takara_tommy_radicon_facotry);
$user->play();
結構時間かかった。 あってるのかなー。。 自信ないやー。。。
でも、とても楽しかったので また、週一とかでチャレンジしてみようと思った。
追記
ユーザーが遊ぶときに 操作するたびにラジコンとリモコンのインスタンス作っちゃうところがイマイチな感じがしますね。組み立てる人と遊ぶ人を分けると良さそう。
— えいる@補助人工心臓で子育て🔥🌇 (@eielh) 2019年12月18日
FB頂いた。確かに play() の度にめちゃくちゃ new instance が作られる。良くない(´・ω・`)
色々加筆してみた。 リモコンの所、まだ何か微妙な気がするなー。