デザインパターン Singleton

| 2008年12月18日 19:39

インスタンスが唯一であることを表現するSingletonパターン。 もっとも非難されてるデザインパターンらしい(汗

Singleton

とりあえずPHP5でのサンプル

サンプルコード


class LoginData
{

    private static $instance = null;

    private $login_time = null;
    private $count = 0;

    private function __construct()
    {
        echo "ログイン成功<br />";
    }

    public static function getInstance()
    {
        if (is_null(LoginData::$instance)) {
            LoginData::$instance = new LoginData();
            LoginData::$instance->setLoginTime();
            return LoginData::$instance;
        } else {
            echo "もう作ってあるからそれ返すよ。<br />";
            return LoginData::$instance;
        }
    }

    public function getCount()
    {
        return $this->count;
    }

    public function setCount($num)
    {
        $this->count = $num;
    }

    public function upCount()
    {
        $this->count++;
    }

    private function setLoginTime()
    {
        return $this->login_time = date("H:i:s");
    }

    public function getLoginTime()
    {
        return $this->login_time;
    }

    function __clone()
    {
        throw new Exception("こぴーは不可だょ。");
    }
}


$user1 = LoginData::getInstance();
$user1->setCount(1);

echo "<hr />";

echo $user1->getLoginTime() . "-->";
echo $user1->getCount() . " 回目のログインだょ<br />";

echo "<hr />";

$user1->upCount();

echo $user1->getLoginTime() . "-->";
echo $user1->getCount() . " 回目のログインだょ<br />";

echo "<hr />";

$user2 = LoginData::getInstance();

echo "<hr />";

$user2->upCount();

echo $user2->getLoginTime() . "-->";
echo $user2->getCount() . " 回目のログインだょ<br />";

echo "<hr />";

$user2->upCount();

echo "user1 : ";
echo $user1->getLoginTime() . "-->";
echo $user1->getCount() . " 回目のログインだょ<br />";

echo "user2 : ";
echo $user2->getLoginTime() . "-->";
echo $user2->getCount() . " 回目のログインだょ<br />";

echo "<hr />";

if ($history === $history2) {
    echo "ぉなじものだょ";
} else {
    echo "ちがうものだょ";
}

echo "<hr />";

// コピー不可
$user3 = clone $user1;

Singletonの使いどころ

いまいち使いどころがわからなかったので 色々と調べてみた。 厳格に適用しようとすると自分が作るレベルのものでは使いどころがないってことがわかったw

Singleton パターン
あるクラスのインスタンスが唯一であることを保証し、そのインスタンスを取得する方法を提供するのがSingletonパターン。 つまり、システムでインスタンスが「ひとつしか存在してはならない場合」、「二つ以上存在しても意味が無い場合(メモリ領域やインスタンス生成のオーバーヘッドがもったいない)」、などがSingletonを適用する場面となる。

二つ以上存在しても意味が無い場合は多々ある。

矢沢久雄の早わかりGoFデザインパターン(7)
さてさて、場合によっては、1つのクラスから1つのオブジェクトだけをしか作れないように制限したいこともあるでしょう。 たとえば、プログラムを実行しているコンピュータやOSなどを表すクラスです。 このようなクラスのオブジェクトは、1つだけ作って共有すべきですね。それを実現するのが、Singleton(一人っ子)パターンです。

なるほど、PEAR::Package::Net_UserAgent_Detectは Singletonが適用されてますね。

Singleton pattern
インスタンスが1つしか存在しないことを保証するパターン システムの中に1つしか存在しないものを表現する

例えば
デバイス (Audio, Displayなど)
ユーザの設定

Singleton pattern メリット・デメリット
メリット
"1つしか存在しない"というのは, プログラミングを行う上でかなり重要
他への影響が少なくなるため, 未然にバグが防げる
後からインスタンスの生成方法を変えることも可能

デメリット
結局, グローバル変数と同じ
違うのはアクセス制御可能であることと, インスタンスが唯一であることを保証できること
本当にそれが1つしか存在し得ないのかどうかを良く考えてから使うこと

デザインパターンの使い方: Singleton
単純に考えると、Singletonパターンの候補としては、図書館システム内のカタログなどが思い浮かびます。どの本がどのカタログに追加されたのかわからないという状況は望ましくないからです。

Singleton
Singletonパターンは、アプリケーション内でオブジェクトが1つしか無い事を保障する生成法です。 オブジェクトが複数あると困る事はたびたびあります。 例えば、ゲーム内で通して使われるグローバルなタイマー。 これが複数あると、ゲームに2つの時間軸が存在してしまうことになります。時計は1つで良いのです。

「グローバルな変数を1つだけ用意すれば?」と考えがちですが、それは作り手側の配慮です。 2つ用意することも出来てしまいます。Singletonパターンは「2つ用意するとエラーになる」くらいの厳格なものなのです。

時間軸。なるほどそういう場合に使うのか。

■[c/c++]Singletonを実現するgetInstanceが推奨できない理由
安易にgetInstanceのクラスを増やすと 「グローバル変数」を増やしているのと変わらないということ それは要するに「密結合」であり、 「依存度の高さを不用意に高めている」ことに他ならない。 だいたい、 「本当にインスタンスが一つであることを完全に保証しなければならない」 ことってそもそもそんなに多発するケースなんだろうか?

「グローバル変数」「密結合」。安易な適用はしないほうがよいのですね。 自分が作るレベルではそれほどってか全然ない。。。

元々、Singletonは 「そのクラス自身を見たとき」 「そのインスタンスが一つしかない事を『表現』する」 ためにあるのであって、 他のクラスから見たとき、それが一つであるかどうかはどうでもいいし、 他のクラスからお手軽に(グローバル的に)アクセスすることを赦すために存在するわけじゃない。 そのインスタンスが単一のものであるかどうかなんてことは、 「そのクラス内で閉じているべき」なのだ。

Singletonパターンを利用する場合は、 よーく考えたほうがよいということがわかった。

PHPによるデザインパターン入門

著者 : 下岡 秀幸 / 金額 : ¥ 3,150

kantenna.com 最新更新ページ

デザインパターン Singletonタグ:

トラックバック

  • http://www.kantenna.com/cgi-bin/mt/mt-tb.cgi/424
コメント (0)
コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)





この情報を登録しますか?