KANTENNA.COM

Solarized

HOME > WEBプログラム覚書 > デザインパターン Singleton

デザインパターン Singleton

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

Singleton

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

サンプルコード

PHP
  1.  <?php
  2.  class LoginData
  3.  {
  4.  
  5.   private static $instance = null;
  6.  
  7.   private $login_time = null;
  8.   private $count = 0;
  9.  
  10.   private function __construct()
  11.   {
  12.   echo "ログイン成功<br />";
  13.   }
  14.  
  15.   public static function getInstance()
  16.  
  17.   {
  18.   if (is_null(LoginData::$instance)) {
  19.   LoginData::$instance = new LoginData();
  20.   LoginData::$instance->setLoginTime();
  21.   return LoginData::$instance;
  22.   } else {
  23.   echo "もう作ってあるからそれ返すよ。<br />";
  24.   return LoginData::$instance;
  25.   }
  26.   }
  27.  
  28.   public function getCount()
  29.   {
  30.   return $this->count;
  31.   }
  32.  
  33.   public function setCount($num)
  34.   {
  35.   $this->count = $num;
  36.   }
  37.  
  38.   public function upCount()
  39.   {
  40.   $this->count++;
  41.   }
  42.  
  43.   private function setLoginTime()
  44.   {
  45.   return $this->login_time = date("H:i:s");
  46.   }
  47.  
  48.   public function getLoginTime()
  49.   {
  50.   return $this->login_time;
  51.   }
  52.  
  53.   function __clone()
  54.   {
  55.   throw new Exception("こぴーは不可だょ。");
  56.   }
  57.  }
  58.  
  59.  
  60.  $user1 = LoginData::getInstance();
  61.  $user1->setCount(1);
  62.  
  63.  echo "<hr />";
  64.  
  65.  echo $user1->getLoginTime() . "-->";
  66.  echo $user1->getCount() . " 回目のログインだょ<br />";
  67.  
  68.  echo "<hr />";
  69.  
  70.  $user1->upCount();
  71.  
  72.  echo $user1->getLoginTime() . "-->";
  73.  echo $user1->getCount() . " 回目のログインだょ<br />";
  74.  
  75.  echo "<hr />";
  76.  
  77.  $user2 = LoginData::getInstance();
  78.  
  79.  echo "<hr />";
  80.  
  81.  $user2->upCount();
  82.  
  83.  echo $user2->getLoginTime() . "-->";
  84.  echo $user2->getCount() . " 回目のログインだょ<br />";
  85.  
  86.  echo "<hr />";
  87.  
  88.  $user2->upCount();
  89.  
  90.  echo "user1 : ";
  91.  echo $user1->getLoginTime() . "-->";
  92.  echo $user1->getCount() . " 回目のログインだょ<br />";
  93.  
  94.  echo "user2 : ";
  95.  echo $user2->getLoginTime() . "-->";
  96.  echo $user2->getCount() . " 回目のログインだょ<br />";
  97.  
  98.  echo "<hr />";
  99.  
  100.  if ($history === $history2) {
  101.   echo "ぉなじものだょ";
  102.  } else {
  103.   echo "ちがうものだょ";
  104.  }
  105.  
  106.  echo "<hr />";
  107.  
  108.  // コピー不可
  109.  $user3 = clone $user1;
  110.  ?>

Singletonの使いどころ

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

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

Singleton パターン

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

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

矢沢久雄の早わかりGoFデザインパターン(7)

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

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

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

Singleton pattern

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

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

Singleton pattern メリット・デメリット

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

デザインパターンの使い方: Singleton

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

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

Singleton

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

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

■[c/c++]Singletonを実現するgetInstanceが推奨できない理由

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

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

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

PHPによるデザインパターン入門
作者:畑 勝也 | 価格:¥ 3,150

トラックバック(2)

2010年2月13日 03:15

[PHP]これはPHP初心者は絶対読むべき!!・・・だとおもう、極上のリソース情報備忘録

これはPHP初心者は絶対読むべき!!・・・だとおもう、極上のリソース続きを読む

2012年1月25日 13:02

オブジェクト指向の間違った理解を正してくれた3つの言葉情報備忘録

オブジェクト指向の間違った理解を正してくれた3つの言葉続きを読む

コメント

コメントする
Name
Email Address
URL
TIME LINE
2012
02.08

[Ubuntu11.10]Winows XPユーザーがUbuntuを使ってみて

Windows XPとUbuntuのデュアルブート環境にしてみておもったこと。

2012
02.03

[jQuery]closest()とparents()

今から16年前Netscapeブラウザのソースコードの公開方法の会議の中で、初めてオープンソースという言葉が使われた今日、 みなさんいかがお過ごしでしょうか。

今回の投稿はそれとは関係のないjQueryのparents()とclosest()が 似てたので何が違うのか試した時のメモです。

2012
02.01

[jQuery Mobile]初期化イベントメモ

jQuery Mobileは読み込まれてから

mobileinit -> pagebeforecreate -> pagecreate -> pageinit

の順番でイベントが発生する。

2012
02.01

[WordPress]管理画面のフッタのフィルタとアクション。

時間も時間なので、あまり使用頻度の高くない微妙なネタを。

会員制サイトなどで不特定多数の人にログインさせる場合、フッタのバージョン情報は隠しておきたかったり、 こじゃれたメッセージを表示したいときとか使うアクションとフィルタ。

2012
01.28

[WordPress] ブログの情報を取得する方法とノーキャッシュ疑惑

ブログのget_bloginfo()で取れないデータが必要な場合に使うもの。

2012
01.26

[jQuery Mobile]ダイアログ

jQuery Mobileにおけるダイアログの扱いはウインドウではなくページ。 なので通常のページと同様に扱える。ダイアログウインドウを出す。じゃなくダイアログページに遷移する。的な。

2012
01.25

[Ubuntu11.10]Ubuntuのインストール後の設定

インストール完了後の環境構築。PC起動時いちいちBIOSからブートドライブ選んで ブートするのかと思ってたら起動時にOS選択画面が出てくる。

すばらしいですね。

2012
01.24
2012
01.23

MinGW+Mintty+Git

MinGW+Mintty+Gitをやろうとして失敗に終わった。このエントリーには収穫できるものはありません。