PHP5.3で継承して使うSingletonをちゃんとやる
発端
02:51:51 (sotarok) で, hoge_klass::get_instance() も,同じように動くようにしたい,でも,hoge_klass には, get_instance を再実装したくないよね
略しすぎてなんだか分からない人のために言っとくと、まぁSingletonの実装ってメンドいから継承したいよねと。
昔、Objective-Cでもそれやったけど
継承して使えるSingletonクラス - ゆどうふろぐ
PHP5.3で遅延静的束縛ができたから、継承できるSingletonを実装できるようになったから。
まぁあちこちサンプルあるけど、なんかcloneとかconstructとかちゃんとやって無いし。
で、まぁノリで書いてみたらfinalとかがcloneやconsructに付けられるという事実が分かって*1、なんか思ったよりきちんと重複を排除できる感じで、継承して使えるSingletonが書けたのでブログに乗っけとく。
<?php class Singleton { private static $instance = array(); final private function __construct() { if (isset(self::$instance[get_called_class()])) { throw new Exception("複数作るなんてできないよ"); } static::initialize(); } protected function initialize() { # ここでコンストラクタの初期化実装 } final public static function getInstance() { $class = get_called_class(); if (!isset(self::$instance[$class])) { self::$instance[$class] = new static(); } return self::$instance[$class]; } final private function __clone() { throw new Exception("cloneなんてできないよ"); } }
試しに継承:
<?php require_once "singleton.php"; class Hoge extends Singleton { public $foo; public $hoge; protected function initialize() { $this->foo = "bar"; } } class Huga extends Singleton { } $aaa = Singleton::getInstance(); $bbb = Hoge::getInstance(); $ccc = Hoge::getInstance(); $ddd = Huga ::getInstance(); $bbb->hoge = "huga"; var_dump($aaa); var_dump($bbb); var_dump($ccc); var_dump($ddd);
結果:
object(Singleton)#1 (0) { } object(Hoge)#2 (2) { ["foo"]=> string(3) "bar" ["hoge"]=> string(4) "huga" } object(Hoge)#2 (2) { ["foo"]=> string(3) "bar" ["hoge"]=> string(4) "huga" } object(Huga)#3 (0) { }
もちろんcloneもnewも、ちゃんとNGでます。
継承してconstructやcloneを実装できちゃう!なんてこともないです。
素敵ですね。
でっていう。
*1:すいません今まで知りませんでした