パーマリンク | 2008年12月18日 19:39
インスタンスが唯一であることを表現する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;
いまいち使いどころがわからなかったので 色々と調べてみた。 厳格に適用しようとすると自分が作るレベルのものでは使いどころがないってことがわかったw
あるクラスのインスタンスが唯一であることを保証し、そのインスタンスを取得する方法を提供するのがSingletonパターン。 つまり、システムでインスタンスが「ひとつしか存在してはならない場合」、「二つ以上存在しても意味が無い場合(メモリ領域やインスタンス生成のオーバーヘッドがもったいない)」、などがSingletonを適用する場面となる。
二つ以上存在しても意味が無い場合は多々ある。
さてさて、場合によっては、1つのクラスから1つのオブジェクトだけをしか作れないように制限したいこともあるでしょう。 たとえば、プログラムを実行しているコンピュータやOSなどを表すクラスです。 このようなクラスのオブジェクトは、1つだけ作って共有すべきですね。それを実現するのが、Singleton(一人っ子)パターンです。
なるほど、PEAR::Package::Net_UserAgent_Detectは Singletonが適用されてますね。
インスタンスが1つしか存在しないことを保証するパターン システムの中に1つしか存在しないものを表現する
例えば
デバイス (Audio, Displayなど)
ユーザの設定
メリット
"1つしか存在しない"というのは, プログラミングを行う上でかなり重要
他への影響が少なくなるため, 未然にバグが防げる
後からインスタンスの生成方法を変えることも可能
デメリット
結局, グローバル変数と同じ
違うのはアクセス制御可能であることと, インスタンスが唯一であることを保証できること
本当にそれが1つしか存在し得ないのかどうかを良く考えてから使うこと
単純に考えると、Singletonパターンの候補としては、図書館システム内のカタログなどが思い浮かびます。どの本がどのカタログに追加されたのかわからないという状況は望ましくないからです。
Singletonパターンは、アプリケーション内でオブジェクトが1つしか無い事を保障する生成法です。 オブジェクトが複数あると困る事はたびたびあります。 例えば、ゲーム内で通して使われるグローバルなタイマー。 これが複数あると、ゲームに2つの時間軸が存在してしまうことになります。時計は1つで良いのです。
「グローバルな変数を1つだけ用意すれば?」と考えがちですが、それは作り手側の配慮です。 2つ用意することも出来てしまいます。Singletonパターンは「2つ用意するとエラーになる」くらいの厳格なものなのです。
時間軸。なるほどそういう場合に使うのか。
安易にgetInstanceのクラスを増やすと 「グローバル変数」を増やしているのと変わらないということ それは要するに「密結合」であり、 「依存度の高さを不用意に高めている」ことに他ならない。 だいたい、 「本当にインスタンスが一つであることを完全に保証しなければならない」 ことってそもそもそんなに多発するケースなんだろうか?
「グローバル変数」「密結合」。安易な適用はしないほうがよいのですね。 自分が作るレベルではそれほどってか全然ない。。。
元々、Singletonは 「そのクラス自身を見たとき」 「そのインスタンスが一つしかない事を『表現』する」 ためにあるのであって、 他のクラスから見たとき、それが一つであるかどうかはどうでもいいし、 他のクラスからお手軽に(グローバル的に)アクセスすることを赦すために存在するわけじゃない。 そのインスタンスが単一のものであるかどうかなんてことは、 「そのクラス内で閉じているべき」なのだ。
Singletonパターンを利用する場合は、 よーく考えたほうがよいということがわかった。
/ 金額 : ¥ 3,150