やる夫がデザインパターンをやるようです 第11回

やる夫がデザインパターンをやるようです 第11回をはてなブックマークに追加 やる夫がデザインパターンをやるようです 第11回をdel.icio.usに追加 Yahoo!ブックマークに登録 やる夫がデザインパターンをやるようです 第11回をGoogle Bookmarksに追加

≪第10回
第12回≫

やる夫で学ぶデザインパターン。ブックマークしていただきまして本当にありがとうございます。これらの説明が正しいか間違っているかは別として(間違いなどありましたらご指摘ください)読み物としてでも読んでいただけるとうれしいです。いつもありがとうございます。

やる夫。インスタンスを一個しか生成させないようにするには
newできるコンストラクタがpublicにあったらだめだろ。
だったらprivateにしてみたらどうなる?
class YaruoGlobal {
private YaruoGlobal(){}
};
こうなるだろ。っていうことh
   / ̄ ̄\
 /   _ノ  \
 |    ( ●)(●)
. |     (__人__)
  |     ` ⌒´ノ
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)
 ぎゃははははははあはhwww
 そんなことしたら誰がnewするんだおww
 コンストラクタはpublicにあってこそ、その機能が解決されるんだお
          ____
        /_ノ  ヽ、_\
 ミ ミ ミ  o゚((●)) ((●))゚o      ミ ミ ミ
/⌒)⌒)⌒. ::::::⌒(__人__)⌒:::\   /⌒)⌒)⌒)
| / / /     |r┬-|    | (⌒)/ / / //
| :::::::::::(⌒)    | |  |   /  ゝ  :::::::::::/
|     ノ     | |  |   \  /  )  /
ヽ    /     `ー'´      ヽ /    /
 |    |   l||l 从人 l||l      l||l 从人 l||l
 ヽ    -一''''''"~~``'ー--、   -一'''''''ー-、
  ヽ ____(⌒)(⌒)⌒) )  (⌒_(⌒)⌒)⌒))
   / ̄ ̄\
 /   _ノ  \
 |    ( ●)(●) だれが?newするか?
. |     (__人__)
  |     ` ⌒´ノ
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く    スッ
   |     \
    |    |ヽ、二⌒) [ YaruoGlobal ]
       ____
     /⌒三 ⌒\  あ
   /( ○)三(○)\
  /::::::⌒(__人__)⌒::::: \
  |     |r┬-|     |
  \      `ー'´     /
class YaruoGlobal {
private YaruoGlobal(){}
public static YaruoGlobal getInstance(){
return new YaruoGlobal();
}
};
これでどうだ。
   / ̄ ̄\  ( ;;;;(
 / _ノ  ヽ\ ) ;;;;)
 |  ( ●) (●)/;;/  
. |   (__人__) l;;,   
  |    ∩ ノ)━・'/  
.  |   /  ノ´ } 
.  ヽ  / /    } 
   ヽ/ /   ノ
       ______
      /  \    /\
    /  し (>)  (<)\
    | ∪    (__人__)  J | ________
    \  u   `⌒´   / | |          |
    ノ           \ | |          |
         ____
      /  \    ─\   チラッ
    /  し (>)  (●)\
    | ∪    (__人__)  J | ________
    \  u   `⌒´   / | |          |
    ノ           \ | |          |
     コンパイルガトオッタオ
         ____
      /::::::─三三─\
    /:::::::: ( ○)三(○)\
    |::::::::::::::::::::(__人__)::::  | ________
     \:::::::::   |r┬-|  / | |          |
    ノ::::::::::::  `ー'´   \ | |          |
アーキテクトが作成したgetInstance()メソッドはクラスインスタンスをnewして返すだけのものです。これにもう少し手を加えて、ある条件下の元、newするようにしてしまえばインスタンスをひとつだけ生成させるクラスができます。それは

class YaruoGlobal {
private static YaruoGlobal uniqInst;
private YaruoGlobal(){}
public static YaruoGlobal getInstance(){
if( uniqInst == null ){
uniqInst = new YaruoGlobal();
}
return uniqInst;
}
};

こんな風に書くことができるのではないでしょうか。

  でも、今までおいらが実装したように
  Javaでいうスタティック変数を使っても
  やりたいことが実現できないことはないお。
      ____
    /_ノ   ヽ_\
   /( ●) ( ●)\
 / ::::::⌒(__人__)⌒:::::\
 |        ̄      |
 \              /
 それはもちろんそのとおりだ。
 今回、お前に覚えてほしいこのシングルトンパターンは
 オブジェクトを1つだけインスタンス化するための規約にすぎない。
 だが、今回のシングルトンパターンを適用すると、
 スタティック変数で保持するより良いこともある。
   / ̄ ̄\
 /   _ノ  \
 |    ( ●)(●)
. |     (__人__)
  |     ` ⌒´ノ
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)
       ____
     /⌒  ⌒\ ホジホジ
   /( ●)  (●)\  はやくいえお
  /::::::⌒(__人__)⌒::::: \
  |    mj |ー'´      |
  \  〈__ノ       /
    ノ  ノ
 ・・・・。
 もし、グローバル変数にオブジェクトを突っ込むと、
 アプリケーションの開始時にそのオブジェクトを生成しなければならない
 ※(実装依存です)
 例えばこのオブジェクトが、あるマスタテーブルなんかを読み込むような
 リソース集約型だとして、さらにこのオブジェクトをアプリケーションが
 最後まで使わなかったとしたら。
   / ̄ ̄\
 /   _ノ  \
 |    ( ●)(●)
. |     (__人__)
  |     ` ⌒´ノ
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)
  ・・・最後まで使わなかったとしたら?
  (ハナシが見えないお。3行でまとめてほしいお)
       ____
     /⌒  ⌒\ ホジホジ
   /( ○)  (○)\  
  /::::::⌒(__人__)⌒::::: \
  |    mj |ー'´      |
  \  〈__ノ       /
    ノ  ノ
 (ハナシが見えないとか思ってんだろうな)
 最後まで使わなかったとしたら。
 アプリケーションにとっては無用なコストとなる。
 だが、シングルトン実装することにより、
 必要になったらオブジェクトを作成できるだろう。
   / ̄ ̄\
 /   _ノ  \
 |    ( ●)(●)
. |     (__人__)
  |     ` ⌒´ノ
.  |         }
.  ヽ        }
   ヽ     ノ
   /    く
   |     \
    |    |ヽ、二⌒)
   3行でまとめてくれお!
   あと1行へらすだけだお!
         ___
       / ⌒  ⌒\
      / (●)  (●) \
    /   ///(__人__)/// \
     |   u.   `Y⌒y'´    |
      \       ゙ー ′  ,/
      /⌒ヽ   ー‐    ィヽ
      / rー'ゝ       〆ヽ
    /,ノヾ ,>      ヾ_ノ,|
    | ヽ〆        |´ |
        / ̄ ̄\
      /       \     1個は保障されてる。
      |::::::        |  ほしいときにくれる。
     . |:::::::::::     | お前もうカエレ。
       |::::::::::::::    |          ....,:::´, .
     .  |::::::::::::::    }          ....:::,,  ..
     .  ヽ::::::::::::::    }         ,):::::::ノ .
        ヽ::::::::::  ノ        (:::::ソ: .
        /:::::::::::: く         ,ふ´..
-―――――|:::::::::::::::: \ -―,――ノ::ノ――
         |:::::::::::::::|ヽ、二⌒)━~~'´
   おいらもう・・・。
   (やっぱり1行へらしてほしいお)
         ___
       / ⌒  ⌒\
      / (○)  (○) \
    /   ///(__人__)/// \
     |   u.   `Y⌒y'´    |
      \       ゙ー ′  ,/
      /⌒ヽ   ー‐    ィヽ
      / rー'ゝ       〆ヽ
    /,ノヾ ,>      ヾ_ノ,|
    | ヽ〆        |´ |
というわけで、今回はシングルトンパターンを学びました。が、実はこれだけでは「インスタンスが1個だけ生成される」というところを保障できないことがあります。それは、マルチスレッドのアプリケーションですと上記の実装では問題が出てくるということです。
どう問題が出てくるのかといいますと、

if( uniqInst == null ){
uniqInst = new YaruoGlobal();
}
return uniqInst;

の条件だけでは、複数のスレッドが同時にifスコープ内にステップすることを想定していない作りになっているということです。uniqInstがnullではなくなるのはnewされた後になりますが、newされる前にほかのスレッドに処理がディスパッチされてifスコープ内にステップしてくることによって、結果コンストラクタは2度(以上)呼び出されてしまいます。
それを避けるために、マルチスレッドであるアプリケーションを実装する際のシングルトンは以下のようにコーディングする必要があります。

class YaruoGlobal {
// volatile指定子はuniqInst変数をYaruoGlobalインスタンスに対して初期化する際に
// マルチスレッドがuniqInst変数を正しく処理できるよう保障するものです
private volatile static YaruoGlobal uniqInst;
private YaruoGlobal(){}
public static YaruoGlobal getInstance(){
// 同期コスト削減のため、まずnullかどうか聞く
if( uniqInst == null ){
// nullなら同期チェックしてnullのままならインスタンス生成
synchronized (YaruoGlobal.class ){
if( uniqInst == null ){
uniqInst = new YaruoGlobal();
}
}
}
return uniqInst;
}
};

≪第10回
第12回≫

コメントをどうぞ