グローバル変数だから?なぜ?
アプリケーションに1つだけ存在すればよい設定値オブジェクトとか、アプリケーションに1つだけのコンテキスト情報とかに使っちゃだめ?
よくわからなかったので調べてみた。
参考
- シングルトンの賢い使用法@developerWorks
- ワタシはSingletonがキライだ
- 例えば, Singleton を避ける
- シングルトンについて思うこと
- 僕はアダム、シングルトン中毒から回復したんだ
- オブジェクト指向 - Singleton パターンの使いどころをまとめてみた - Qiita
悪い点
グローバル変数は悪≒ 密結合は悪
Singleton は単体テストの敵
- Singleton では, このガベージコレクションによる状態のクリアが起こらないため, 前のテストコンテキストを引きずったまま, 次のテストを実行することになってしまいます.
複数のテストが影響し合うことによりメンテナンス性が下がるだけでなく, 暗黙的なコンテキストの増大により, 理解もしづらくなります.
- Singleton で実装したクラスそれ自体だけでなく, それを呼び出すクラスにまで, テストのしにくさが伝染してしまう可能性があるのです.
このブログでは説明に Config が使われてて、それこそシングルトンに Config を使ってたので参考になった。
- サブクラスへの差し替えが困難
- シングルトンを参照するクラスが結果的にシングルトンになる
- ライフサイクルの管理が困難
- 複数インスタンス化出来た方が良い事が分かった際の影響が絶大
こっちでは、 GlobalContext クラスで説明。
- 依存関係を見えにくくし、コードが読みづらくなる。
- ユニットテストを難しくする。外部から渡せないオブジェクトはモックにする事が難しい。
- プログラムの再利用性が低下する。一度しか使わないからとシングルトンで作ってしまうと複数のユーザーから利用されるような場合に対応できなくなる。
- スケーラビリティが低下する。
- 良いオブジェクト指向の設計とは言えない。
解決策
- 状態を初期化できるようにする
- 依存性の注入 (Dependency Injection) の利用
シングルトンの使いどころ
クラスが本当にシングルトンであるか否かを決定するためのいくつかの質問があります。
- すべてのアプリケーションは、まったく同一の方法でこのクラスを使用するか? (「まったく」がキーワード)
- すべてのアプリケーションは、常にこのクラスの1つのインスタンスのみを必要とするか? (「常に 」と「1つの」がキーワード)
- このクラスのクライアントは、自分自身がその一部に含まれているアプリケーションを意識しないべきか?
雑感
それでも、コンストラクタでインスタンス指定だと、インスタンス作成時に次々に受け渡していかなくちゃいけない。これって密結合じゃないの?とか思う。
でも、わかった次からは設定とかアプリケーション状態でもシングルトンつかわずにやってみるよ。