質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.04%

シングルトンがなぜ必要なのか

解決済

回答 8

投稿 編集

  • 評価
  • クリップ 20
  • VIEW 30K+

bananafish

score 63

自分がインスタンスというものを決まり文句としてしか理解できていないからなのですが、シングルトンの重要性があまりわかりません。
調べてみてもいまいちピンきませんでした、インスタンスがなぜ一つじゃないといけないのか,どのような場面でシングルトンを使うのか、どなたか教えて頂けないでしょうか。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 8

checkベストアンサー

+21

インスタンスがなぜ一つじゃないといけないのか

使えるリソースが一つだけの場合、それにアクセスするクラスインスタンスも一つだけの方が都合が良い場合が多いからです。

例えば、画面に何か出力するとき、JavaではSystem.outを使いますが、それは「標準出力」というたった一つしかないリソースに対してアクセスを行うために、staticフィールドで定義されたインスタンスであり、staticなのでプロセス内には1個しかインスタンスがありません。

なぜそうしているのかというと、画面に何か書きたいときに、いちいちnewしてクラスインスタンスを作るのは面倒だし、そのたびにnewしていたら無駄にメモリを食うし、それを避けるために一度newしたものを別のクラスでも使い回そうとすると、そのインスタンスの受け渡しをどうするのかという問題が出てくるし……。
ということで、staticフィールドにインスタンスを作ってそれをみんなで使い回すことにするのです。

どのような場面でシングルトンを使うのか

シングルトン(パターン)はインスタンスを一つしか作らないことを「保証する」ための仕組みです。
ただ単にインスタンスを一つにしたいというだけならstaticフィールドにすればできますが、それを知らずに誰かがnewしてしまったらインスタンスが複数になってしまいます。あるいは、staticフィールドにインスタンスを作りたいけど、初期化の順番をコントロールしたい、というケースもあるかもしれません。マルチスレッドでの動作を考慮しないといけないかもしれません。
そういうときに一手間かけてシングルトン(パターン)を使います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/02 15:16

    こんなにたくさんの方に答えてもらえるとは思っていなかったのでとてもうれしいです、みなさんありがとうございました。
    おかげさまでなんとか概念や使用用途などについてはわかりました、あとは実戦でどんどん慣れていけたらと思います。

    キャンセル

  • 2016/06/02 18:37

    > あとは実戦でどんどん慣れていけたらと思います。

    それ大事ですね。いろんなプログラムを作って経験を積むことで「こういうときにはああすれば良い」という勘のようなものが身についていくと思います。
    頑張ってください。

    キャンセル

+8

例を示します。
1個しかない定義ファイルを読み込んで定義情報を保持するクラス Config を作ったとします。
シングルトン設計でない場合、Config を次のように使います。

Config c = new Config();   // Config のコンストラクタで定義ファイルを読み込む
String name = c.getName(); // 定義されている名前を取得

上記の使い方では、new 演算子を実行するたびに、Config のインスタンスが生成されます。
すると、定義ファイルが1個しかないにも関わらず、Config のインスタンスを生成するたびに、定義ファイルを読み込むことになります。

そこで、次のように Config クラスを改善します。

  1. Config クラスのコンストラクタを public にしないように修正し、
    外部プログラムで new 演算子でインスタンスを生成できなくする
  2. Config クラスに getInstance() を追加し、
    Config 内部で保持しているインスタンスを返す

すると、プログラムでは次のような使い方になります。

Config c = Config.getInstance();   // 生成済みの Config インスタンスを取得
String name = c.getName();         // 定義されている名前を取得

この改善により、ただ1つのインスタンスを使いまわすようになります。
そうすれば、定義ファイルを読み込む回数も1回だけになります。

インスタンスを1個しか作らせたくない場合に、シングルトン設計をします。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

ログ出力などが例になりますかね?
javaなどでは同一ファイルに対するファイル出力のストリームを複数持つことはできません。
だからシステム全体で同一のインスタンスから出力できるようシングルトンで保持する必要が発生するのだと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

例えば山田さんがいたとします。
山田さんは手帳を持っています。手帳にはスケジュールを記入します。
しかし、山田さんがたくさん手帳を持っていたらどうでしょう。
明日のスケジュールは青色の手帳、
明後日のスケジュールは赤色の手帳、
来週のスケジュールは緑色の手帳と、
バラバラの手帳にメモしたとすると、いざスケジュールを確認するとき、どの手帳を見ていいかわかりません。

しかし、手帳が1冊しかなければ、書き込むのも確認するのも1冊を見ればよいことになります。
シングルトンとはそういうことです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

一人ではなく、複数人がプログラミングしていると考えてください。

例えばAさんがA機能、BさんがB機能を作っていたとします。Cさんはそれぞれで使うクラスを定義しています。
A機能とB機能のそれぞれで使うインスタンスをすべてCさんが作ったクラス定義からインスタンス化したとします。

この時にアプリケーション的に1つしか存在しないインスタンス(OS、ファイルアクセスクラスやDBアクセスクラス等)を各自が自由にインスタンス化し変更すると各インスタンス間で不整合が起きないように同期を取る必要が出てきます。

このような不整合が起きないようにするには難度が高く誤りが起こりやすくなります、そこでCさんがシングルトンパターンを適用しアプリケーション内でインスタンスが1つになるように保証します。1つのインスタンスはどこで値が変更されても不整合が起こり得ないので同期も必要ありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

シングルトンを使わないほうがいいケースもあります。

オブジェクトの状態が更新されるようなクラスはシングルトンにしてはいけないです。

他の方の回答にもあるように、リソースが単一で不変なオブジェクトに対してのみシングルトンを検討するべきです。

更新が必要なオブジェクトをシングルトンにしてしまうと、他のスレッドと更新が競合しないようにsyncronizedなどで排他制御を行う必要が出てきて、オーバヘッドが発生します。

ですので、シングルトンは値オブジェクトであるべきです。シングルトンはメモリ効率がよく、アクセシビリティも高いので便利ですが、なんでもかんでもシングルトンは危険ですのでそこだけ注意してください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

インスタンスがなぜ一つじゃないといけないのか

制限として1つしか持てないオブジェクト(A)があり、複数のオブジェクトから
利用したいとすれば、Aを利用する機能はシングルトンとする必要があります。
tkturboさんの回答はこの例です。

オブジェクトの実装の制限により、1つじゃないとダメになることがあります。
例えばインスタンス生成時に何かの処理を行う人がいて、その処理を一回だけ、
実行して欲しいという場合。
「一回しかしないでね!」とお約束するよりも、機能として一回しか実行されない
ことを保証するのが良いのは言わずもがな。
その実現方法として、シングルトンという選択があります。
sipadan2003さんの回答がこの例です。

どのような場面でシングルトンを使うのか

上記の通り、シングルトンじゃないとダメって時は、当然そうします。
他の方法で回避できる場合もありますが、この辺は設計次第です。

他には、あるオブジェクトをみんなが共有して使いたいという時がたまにあります。
全部の機能にオブジェクトの参照を渡すのが大変。ってとき、シングルトンだと楽です。
Cならグローバル変数を使えば共有できますけど、私はシングルトンの方が好きです。

また、なにかしらの理由でスゴイサイズのメモリをアロケートしなければならない等、
オブジェクトのサイズが非常に大きい場合もシングルトンを選ぶことがあるかと思います。
インスタンスがたくさんできるとメモリを圧迫してしまうからですね。

絶対にシングルトンじゃないとダメ!!というのは、どちらかと言えば稀です。
シングルトンは、デザインパターンの一種で、設計時の選択肢の1つです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

最近しみじみと必要性を感じたので一言だけ。
データベースを作っていたのですが、AさんからのINSERTはBさんも見れなくてはなりません。
今回作成したのはインメモリDBでしたので、実体がAさん用、Bさん用に出来ては不都合です。
よって単一のリソースを復数人数で参照するにはシングレトンが必須でした。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる