シングルトンパターンの使い方

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ラミー

シングルトンパターンの使い方

#1

投稿記事 by ラミー » 9年前

最近、デザインパターンの勉強を始めました。
まずはシングルトンパターンの章なのですが、
要約すると、シングルトンではプログラム内のどこにいても、プログラム内に一つのみ存在できるオブジェクトにアクセスできる
というものでした。

プログラムを書いていて、一つのオブジェクトをあらゆるクラスのメソッド内で使用する必要がでてきました。
(それが良いかどうかは置いておいて)
そこで、シングルトンパターンを使わない場合は、
オブジェクトを引数経由で(ポインタや参照で)あらゆる箇所に引き回す必要があります。
シングルトンを使えば、アクセス用のstatic publicメソッドがあるので、引き回す必要はありません。
実際の使い方として、どちらが一般的なのでしょう?
シングルトン使わなければ、関数の引数を見ただけで、ここで使っているオブジェクトは何であるかを
知ることができる、というメリットがあるかと思うのですが。

アバター
usao
記事: 1887
登録日時: 11年前

Re: シングルトンパターンの使い方

#2

投稿記事 by usao » 9年前

あくまでも個人的見解と言うかそんな ふわっとした 話ですが…

>引き回す必要はありません。
私は なんとなくですが, このことはそれほどメリットとは思えないというか,むしろ
コードのどこからアクセスされるかわからないという外部変数的オブジェクトになってしまうデメリットが大きいような気がします.
毎度引数に渡す面倒さをなんとかしたいとかいう話なら,シングルトンでない別の方法,例えば
初期にオブジェクトのポインタとかを「以降,これを使ってね」って感じで指定しとくとかでも良いと思います.

シングルトンって 「その型のオブジェクトを2つ以上作れないように言語機能的に(わざわざ)縛る」 という話だと思うので
【こっち側の話に本当に必要性があるのか?】
という事柄を このパターンを使用するか否かの判断材料としています.(そしてその結果として,全く使う機会が無いです)
オフトピック
多人数でやるときに 勝手にぽこぽこインスタンスを作られるとやばい みたいなのがある場合とか(?)に
それを抑制するための手段なんじゃないだろうか? とか.
(実際どんなときに使うのが 一般的 なのかわからんです…)

アバター
nullptr
記事: 239
登録日時: 12年前

Re: シングルトンパターンの使い方

#3

投稿記事 by nullptr » 9年前

オブジェクト指向的な設計をするのであれば、シングルトンパターンを使うことは基本的にあってはなりません。
シングルトンを使うべきなのは、OSレベルなど下層のシステムにおいて「1つでなければならない」「1度でなければならない」と決められている場合のみに使うべきです。


そもそも生成できるインスタンスが1つでなければならないことなど、実際にはまずありません。
拡張を考えた場合に、シングルトンパターンでは何もできません。シングルトンは完全に閉じたコードになります。
また、シングルトンであるということは、実際にはアクセスする必要のない場所からもアクセスできてしまうということです。これはカプセル化の概念を破壊します。
つまり、シングルトンは非オブジェクト指向的であるということです。これは拡張性の欠乏、管理の複雑化など様々なデメリットを意味します。
だからよく「シングルトンはグローバル変数と変わらない」と言われるのです。更に、シングルトンには初期化順序の不定という問題もあります。


このパターンは、先述の通り自分のプログラムではどうしようもない部分の為に使用すべきだと思います。


時々、引数でインスタンスをひきまわすの嫌だという方を目にします。
もし引数で回す数が異常に多いなら設計的な問題であるし、そもそも引数で渡すのが無駄に思えるのであればC言語でグローバル変数をいっぱい書けばいいと思います。
引数で渡すことが、1つのカプセル化の手段なのです。
実際の使い方として、どちらが一般的なのでしょう?
ここまで話したのは、「オブジェクト指向的な設計」の話です。
C言語のような、非オブジェクト指向的なプログラミングをするのであれば「一般的」とは言い難いでしょう。
C++のようにマルチパラダイムな言語であれば、一般的の定義は更に困難です。
規模の小さな、使い捨てのコードであればシングルトンにしてしまうのも1つの選択肢であると思います。デメリットを理解した上で使うのなら自己責任で十分良いと思います。
規模の大きなプログラムになれば、自ずとシングルトンの面倒臭さを理解すると思います。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

dic
記事: 657
登録日時: 13年前
住所: 宮崎県
連絡を取る:

Re: シングルトンパターンの使い方

#4

投稿記事 by dic » 9年前

新ゝ月 さんが書きました:つまり、シングルトンは非オブジェクト指向的であるということです。
デザインパターンにはオブジェクト指向が前提にあります。非オブジェクト指向である理由を挙げてくれると助かります。

新ゝ月 さんが書きました:これは拡張性の欠乏、管理の複雑化など様々なデメリットを意味します。
よくわかりません。シングルトンに拡張性をもたせればいいのではないでしょうか。
管理はいたって簡素です。複雑というのがよくわかりません。

新ゝ月 さんが書きました:だからよく「シングルトンはグローバル変数と変わらない」と言われるのです。更に、シングルトンには初期化順序の不定という問題もあります。
グローバルに扱える、唯一のオブジェクトであることを保証します。
グローバル変数とイコールではありません。

新ゝ月 さんが書きました:規模の大きなプログラムになれば、自ずとシングルトンの面倒臭さを理解すると思います。
どのような業務や、内容のプログラムだと、シングルトンの面倒くささを理解できるのでしょうか?
実例を挙げてくれると助かります。



シングルトンパターン、デザインパターンを利用することのメリットですが、
これを利用することによって、デザインパターンを知っている人にとっては、一瞬でコードが理解できます。
シングルトンパターンでのコードを見れば、「あっ、これはオブジェクトがひとつだな」とわかります。
シングルトンパターンを利用していないと、どこかでオブジェクトの内容が変更されたり、コピーされたり
する可能性が残りますし。ソースを全部読まないと理解できないと思います。
引数に渡すと、コピーコンストラクタ、デストラクタなどの問題が出てきて、こちらの方が複雑に感じます。

ISLe()

Re: シングルトンパターンの使い方

#5

投稿記事 by ISLe() » 9年前

シングルトンは唯一のインスタンスを保証する仕組みですが、そもそも『どういう状況に対して』保証するかという点は定義されてないですよね。

例えばプロセスではないコンテキストで分離されたプログラムを並行動作させるシステムがあったとしたら、シングルトンは、現在選択されているコンテキストに結び付いたインスタンスを返すことを求められるでしょう。

そもそもPC以外で何の引数もなしに静的関数でシステムに関連するコンテキストを持つオブジェクトを生成したりはできない環境が多いです。
システムに関連するコンテキストをひとつにまとめたオブジェクトを作成して引数で回すのは移植性を考慮したものではないかと思います。

ところで、引数で回したオブジェクトから取得するインスタンスがそのアプリケーションプログラム内で唯一であることが保証されているとき、それはシングルトンとは呼ばないのでしょうかね。

アバター
nullptr
記事: 239
登録日時: 12年前

Re: シングルトンパターンの使い方

#6

投稿記事 by nullptr » 9年前

全体的に言葉が足らぬ点、申し訳ありません。
デザインパターンにはオブジェクト指向が前提にあります。非オブジェクト指向である理由を挙げてくれると助かります。
非オブジェクト指向的(な考えである)と述べたまであって、オブジェクト指向ではないとは言ってないはずですが。
引用の前文に書きましたが、インスタンスがアクセスできる範囲を限定できない点について、カプセル化を妨げるという理由からです。
オブジェクト指向が前提にあるからといって、オブジェクト指向的であるとは限らないと思います。シングルトンは「インスタンスの唯一性を保証する」と銘打ってはいますし、その点のみに関して言えばオブジェクト指向です。しかし副作用としてオブジェクト指向とは言い難い状況ができかね無いと指摘しているのです。
プログラム単位で唯一性を保証する機会などそうそうあるものではないと思います。プログラム単位で唯一性を保証することに大きな正当性があるのなら、私はシングルトンを否定する気はありません。

よくわかりません。シングルトンに拡張性をもたせればいいのではないでしょうか。
管理はいたって簡素です。複雑というのがよくわかりません。
拡張性について)シングルトンとは、型にインスタンス(値)の制限を与える設計故に、型を継承するなど再利用することはできません。

管理について)私には、「グローバル変数の方がコードが書きやすい」と言っているのと同じに聞こえます。
それと管理に関して、「シングルトンの管理」ではなく「プログラム全体の管理」の点に留意下さい。
グローバルに扱える、唯一のオブジェクトであることを保証します。
グローバル変数とイコールではありません。
イコールと言ったつもりはありませんが。「だからよく「シングルトンはグローバル変数と変わらない」と言われるのです」という部分はイコールの意味になってしまうのでしょうか。
「だから」といったとおり、前文における特徴に関して、「グローバル変数と変わらない」と言っただけです。
どこからでもアクセスできるという特徴故、どこかで誰かがインスタンスを操作してもおかしくない以上、グローバル変数が避けられるのと同じ理由で管理に支障を来すと考えます。

シングルトンを使ったほうが見通しがよくなる事があるのは確かです。しかしそれは「全て見通さないといけない」ようなコードの規模の場合だけだと思います。
「見通しきれない」規模になった時、どこで何をされているかわからないです。
どのような業務や、内容のプログラムだと、シングルトンの面倒くささを理解できるのでしょうか?
実例を挙げてくれると助かります。
「規模の大きなプログラムになれば、自ずとシングルトンの面倒臭さを理解すると思います。」というのに関してはあくまで私的な論なので、理解できなければ無視して下さい。さして根拠があるわけでもないので。
シングルトンパターン、デザインパターンを利用することのメリットですが、
これを利用することによって、デザインパターンを知っている人にとっては、一瞬でコードが理解できます。
シングルトンパターンでのコードを見れば、「あっ、これはオブジェクトがひとつだな」とわかります。
私にはいささか共感しがたいですね。そもそもマルチスレッドにおける「唯一の」インスタンスの在り方や、実装方法は定義されていません。
シングルトンパターンを利用していないと、どこかでオブジェクトの内容が変更されたり、コピーされたり
する可能性が残りますし。ソースを全部読まないと理解できないと思います。
正直何をおっしゃっているのかわからないのですが、「シングルトンパターンを利用していると、どこかでオブジェクトの内容が変更されたり、コピーされたりする可能性が残りますし。」の間違いでしょうか?
そもそも変更したりコピーしたりできる範囲を制限すれば良い話なのです。そのためのカプセル化であり、シングルトンはそれができないです。どこで変更されるかわからないのはシングルトンの方だと思いますが?
引数に渡すと、コピーコンストラクタ、デストラクタなどの問題が出てきて、こちらの方が複雑に感じます。
「問題」が指すものが不明瞭です。コピーコンストラクタ?参照を使わないのでしょうか。デストラクタにおいてもデストラクタの呼び出される順序のわからないシングルトンの方がよほど複雑かと思いますが。デストラクタそのものが問題なのですか?
ところで、引数で回したオブジェクトから取得するインスタンスがそのアプリケーションプログラム内で唯一であることが保証されているとき、それはシングルトンとは呼ばないのでしょうかね。
引数で回すオブジェクトの型のインスタンスの生成者を制限できるのなら、有用かもしれません。しかし生成者の制限をするのであればシングルトンパターンの範疇を超える気がします。それはもはや別のデザインパターンであるように私は感じます。インスタンスの生成者を制限しないのなら、普通のシングルトンと変わらないですが、問題点もかわらないと思います。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: シングルトンパターンの使い方

#7

投稿記事 by softya(ソフト屋) » 9年前

話の流れから、宗教論争パターンに入りそうな印象を受けました。
とりあえずシングルトンパターンが書籍にも載るほど有名で存在するのは確かですし、不要論に関しては別トピックで話されては如何でしょうか?

【補足】
質問の起点にシングルトンパターンがあるのが原因だと思いますが、初心者が迂闊に引数で持ちまわるとメンテナンス性が大幅に下る設計をしてしまうのも事実です。
シングルトンパターンを使わない現実的な対処法や、シングルトンパターンを使ったほうが良いかもしれない現実的な対処法など辺りで留めて頂ければ幸いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
nullptr
記事: 239
登録日時: 12年前

Re: シングルトンパターンの使い方

#8

投稿記事 by nullptr » 9年前

失礼しました。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: シングルトンパターンの使い方

#9

投稿記事 by softya(ソフト屋) » 9年前

質問者そっちのけになりそうなので、言葉を挟まさせていただきました。
ラミーさんの再登場を待たれたほうが良いと思います。
ラミーさん中心で色々話しをした上で、ラミーさん手助けになる対処法が見つかれば良いなと思っております。

【補足】
新ゝ月さんの返答時の引用が誰のものか分かりづらいので、ちょっと話の流れがつかみにくいです。ご考慮下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

zeek

Re: シングルトンパターンの使い方

#10

投稿記事 by zeek » 9年前

ラミー さんが書きました: プログラムを書いていて、一つのオブジェクトをあらゆるクラスのメソッド内で使用する必要がでてきました。
(それが良いかどうかは置いておいて)
そこで、シングルトンパターンを使わない場合は、
オブジェクトを引数経由で(ポインタや参照で)あらゆる箇所に引き回す必要があります。
シングルトンを使えば、アクセス用のstatic publicメソッドがあるので、引き回す必要はありません。
実際の使い方として、どちらが一般的なのでしょう?
アプローチの方向に違和感を感じます。
「一つのオブジェクトをあらゆるクラスのメソッド内で使用する」ことと「対象ソフトに置いてオブジェクトを1つにすべきものか」とは直接関係しないですよね。
シングルトンパターンを使うのは、アプリケーションのデフォルト設定クラスや LOG クラスといった「対象ソフトで1つだけのオブジェクト」で違和感がないものにすべきではないかと思います。

アバター
usao
記事: 1887
登録日時: 11年前

Re: シングルトンパターンの使い方

#11

投稿記事 by usao » 9年前

オフトピック
>デザインパターンの勉強を始めました
…という話なので,「使って(触れて/試して)みること」自体に意義がある気もしますし,
一般的な方法が何か? みたいなことには現段階ではさほど拘らずに
{使う/使わない}両パターンを書いてみるとかして
効果や使い勝手の実感を実際に得てみるのが良いのではないでしょうか.

想定する状況下において,単に

コード:

//外部変数に毛の生えたような…
Test &TestInstance()
{
  static Test inst;
  return inst;
}
みたいなのだけでも十分なのか?ダメなのか? …みたいな考察だとか.

閉鎖

“C言語何でも質問掲示板” へ戻る