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

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

新規登録して質問してみよう
ただいま回答率
85.50%
オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

デザイン

プログラミングでのデザインとは、プログラムの構成や、使用の信頼性・持続性・正確性・利便性の目標達成にはどうするのがベストなのか特定の選択を行うことです。

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

10回答

9137閲覧

デザインパターンシングルトン、オブジェクト指向について

_Victorique__

総合スコア1392

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

デザイン

プログラミングでのデザインとは、プログラムの構成や、使用の信頼性・持続性・正確性・利便性の目標達成にはどうするのがベストなのか特定の選択を行うことです。

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2017/04/22 20:51

編集2017/04/22 21:12

###前提・実現したいこと
デザインパターンにおけるシングルトンパターンについて
自分の書き方はシングルトンパターンなのか

###発生している問題・エラーメッセージ
自分の書いているコードがシングルトンパターンなのかわかりません。シングルトンを意識して書いていたわけではないのですが、インスタンスを一つしか生成しない点ではシングルトンパターンっぽいけど本質とは全然違う気がします。そもそもオブジェクト指向になっているのかも分かりません。

###該当のソースコード

C++

1//A.h 2class A 3{ 4 //内容A 5}

C++

1//B.h 2class B 3{ 4 //内容B 5}

C++

1//C.h 2class C 3{ 4 //内容C 5}

C++

1#include<iostream> 2#include< A.h > 3#include< B.h > 4#include< C.h > 5 6int main(){ 7 A a;//インスタンス 8 B b;//インスタンス 9 C c;//インスタンス 10 /* 11 処理 12 */ 13 return 0; 14}

###補足情報(言語/FW/ツール等のバージョンなど)
言語はC++。Pythonでも同じような感じで作っています。
シングルトンのように専用のクラスを作ったり、コードとして保証している訳ではありません。それは分かって欲しいです。シングルトンで書かれたコードは見たことがあります。それのコードを回答として貼られても回答になっていないのでご容赦ください。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答10

0

蛇足コメントで恐縮ですが、みなさんがおっしゃる点と質問者さんの感覚には温度差があるように見えました。

  1. 自分が設計したコードを自分自身が使い方を分かっていて使うという感覚
  2. 自分が設計したコードを他者(もしくは時間がたって使い方を忘れてしまっているかも知れない自分)が使っても間違いのない使い方が保証できるという安心感を望む感覚

質問者さんは特定のクラスのインスタンスを一つしか実体化しないコードであることをもってそれを「シングルトン」と呼んでもいいと思っておられます。これは1.の感覚ではないかと思います。

一方、デザインパターンを始めとする様々な方式・パラダイムは「人間は勘違いしたり忘れたりすることで間違いを犯す。プログラマーが少しでも幸せになるためには間違いを排除することが重要であり、方法論にはそのことの配慮が含まれているべき」という思想が大前提として根底に流れています。つまり前述の2.の観点で多くの方法論は議論されるわけです。

自分はクラスA,B,Cが「シングルトンに通じるもの」と考えることはデザインパターンの実例を学んでいく過程においては大事な気づきだと思います。ただ、他者を含めて「シングルトン」という言葉で概念を共有するには一般にシングルトンが備えるべきことは何かを知ることもまた大事と思います。両方を通じて多くの人と齟齬なくコミュニケーションが取れるようになっていくと思います。

投稿2017/04/23 06:15

KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

いいえ、シングルトンパターンではありません。

シングルトンパターンとは、シングルトンとして定義されたクラスについて、「インスタンスを一つしか作らない」ではなく、「インスタンスを一つしか作ない」ようにするデザインパターンです。つまり、二つ目のインスタンスの生成が原則不可能にすることで、そのクラスのインスタンスが全て同一であることを保証するのが目的です。保証が無ければシングルトンパターンではありません。

クラスをシングルトンにする方法ですが、言語によって様々です。C++では全てのコンストラクタをprivateにして、常に同じインスタンスを返すstaticなメンバー関数経由でしかインスタンスを作れない(取得できない)ようにします。Pythonでは__new__を上書きして、常に同じインスタンスが生成されるようにします。他にも、モジュールをMix-inする(Ruby)とか、シングルトンになるオブジェクトを直接定義する(Scala)とか、様々です。同じ言語であってもスレッドセーフにするかしないかでも書き方が変わってきます。

投稿2017/04/22 21:24

raccy

総合スコア21733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

_Victorique__

2017/04/22 21:31

保証するのが目的なのは分かっています。 聞きたいのはそういうことではなくて、そういう保証がされた状態で書けるプログラムを書いた場合には上記のような感じになるのか、という意味です。また、それがそもそもオブジェクト指向として正しいのかということです。 素人なので変な質問ですが申し訳ないです。
raccy

2017/04/22 21:42

C++でシングルトンパターンを実装する場合、コンストラクタをprivateにする必要があるため、クラス内部以外からコンストラクタを直接呼び出せるような書き方にはなりえません。つまり、`A a;`のようなインスタンス生成がクラス外にある書き方にはなりません。 ただ、これはC++に言えることで、他の言語では異なります。Pythonはオブジェクト生成(__new__)自体を上書きできるため、通常のインスタンス生成と同じ書き方をクラス外で使ってもシングルトンにすることができます。
guest

0

ベストアンサー

回答者からは実際のコードが確認できませんが、例えばclassAを実際に複数生成すると動作が成り立たず、それをあなた自身が分かっていて、それを理解したうえでmain関数を書いているならば、classAはシングルトンパターンであるべきクラスであるとは言えると思います。

ただし現状ではシングルトンパターンであるとは言えません。やろうと思えば複数生成できてしまうからです。
シングルトンパターンとは、複数生成されると困るクラスについて、クラス側で複数生成されようとした時にも不具合を起こさないように制御することがパターンの狙いの本質だと理解してください。

認識の違いの一点として、シングルトンパターンは提示のコードのmain関数に対して合致するものではなく、classA~Cのようなクラス定義に対して合致するものであるという認識が弱いのではないかと予想します。
main関数で一つしか作らないからといってそれはシングルトンパターンとは全く関係がなく、classA~Cのコーディングとして複数生成時の制御をかけるということがシングルトンパターンです。

投稿2017/04/23 00:24

編集2017/04/23 00:29
akabee

総合スコア1947

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

シングルトン自体は概ねアンチパターンと化しています… ということを誰かに書いといて欲しかったなぁ… と思うのでクローズされていますが追記です。
なお、これはVictoriqueさんのコードがシングルトンというのではありません。


まず初めに、シングルトンパターンはさておき、シングルトン自体は「1個しか作らない」とか「作れない」ということではありません。

ただこれは「シングルトン」の定義が今現在明確になっているというわけではありません。 経験的にシングルトンな性質が他のオブジェクトに伝播するため暗黙的共通認識…みたいなものです。 シングルトンというのは言葉の定義から曖昧です。 シングルと比べると、特定的な個人である(ファミリーではない)、というような意味です。

もしもclass A, B, Cを何度インスタンス化しても、全てのABCで同一の情報を共有できるならそれはシングルトンと同一の特性を持ちます。シングルトンパターンは使っていませんが、それでもほぼシングルトンと言っていいでしょう。
これはシングルトンパターンを使ったオブジェクトと蜜結合する他のオブジェクトに実際に頻繁に起こる問題です。
シングルトンと結合したクラスは実質シングルトンになります。

シングルトンがオブジェクトの依存関係の不鮮明化、蜜結合を引き起こします。
シングルトンとロジックを結合させる行為は明確にアンチパターンです。
それではグローバル変数の乱用と変わりありません。
安易なシングルトンパターンの適用は忌避されます。

シングルトンパターンを使うのが最適な状況というのからして本来少ないのです。
使う場合もインターフェースを使い、コンストラクタインジェクション等で直接的な結合を避けるように指導することが多いです。
シングルトンパターンは古く、選択的なシングルと付き合うことを目的としたより進化したデザインパターンが登場しています。 > Dependency Injection パターン

シングルトンパターンが解決したかったことも、シングルトンにすることではありません。

何故アンチパターンになるのか、具体的に書くと長くなりすぎるため、警鐘のみに留めておきます。

> シングルトンパターン アンチパターン

投稿2017/04/26 02:45

編集2017/04/26 02:55
haru666

総合スコア1591

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

_Victorique__

2017/04/27 10:25

ありがとうございます!デザインパターンについては無知なので勉強中です。参考にさせていただきます。
haru666

2017/05/30 01:14 編集

もうちょっと簡単にすると ・フレームワーク的なコード(ドメインロジックに関係の無いコード) ならOKと考えています。 フレームワーク的な、とは大体は、それ自体が他のコードとのバスの役割を果たすコードです。 AbstractFactory/Builderパターンはそうです。 その最たるものがロガーですし、グローバルな設定口を持ったフレームワークは結構あります。 ドメインロジックとしてシングルトンを使う時は、(より良い方法があるから)ありません。 Propertyパターンは、String.Emptyみたいなものですかね。 ある状態としてのオブジェクトを使いまわすためのシングルトンというのはありますね。 あえてシングルトンにする必要はないですが、イミュータブルクラスのメンバにstaticなDefaultインスタンスを付加するというのはよくやりますね。
guest

0

こんにちは。

シングルトンの特徴は、他の方もおっしゃっているようにインスタンスを1つしか作れないことが最大ですが、もう一つあります。その唯一のインスタンスにグローバルにアクセスできることです。

密な関係にあるクラスや関数には、インスタンスを引数等で次々と渡すことが多いので、その間で1つのインスタンスを共有することは良く行われます。
その場合にまでシングルトンを使うかというと、わざわざそのようにしない人が大半と思います。インスタンスを1つしか作れないということは汎用性が劣化しています。必要もないのに、使いにくくするのは愚かですから。

逆に、関連性の低いクラスや関数でも、同じインスタンスを使いたい場合があります。Zuishinさんが例に出されている「設定」や、ロガーなどもその1つでしょう。
そのような関連性の低いクラスにも、そのインスタンスをバラメータで引き渡すのは却って可読性を下げるし、メンテナンス性も劣化します。素直にグローバル変数にするべきでしょう。

この場合、きちんとドキュメントに使用するべきグローバル変数を記述し、かつ、ローカルに生成するなと書いておく必要があり、かつ、プログラマはその記述をきちんと読み、覚えるか、必要に応じてドキュメントを確認する必要があります。
作業が増えるので生産性は劣化します。更に、もし書き損なったり読み損なったりして、ローカルに生成するとバグを生み、大きく生産性を落とします。

その時、ローカルにインスタンスを作れなくしてそのようなミスを防ぐ効果があるのがシングルトンです。デバッグする時、そのような間違いを疑わないで済むのでたいへんありがたいです。

投稿2017/04/23 03:47

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

例えばアプリケーションの設定ファイルを読み書きするクラスを作ったとします。
このクラスはインスタンス生成時に設定ファイルを読み込み、Save() が呼ばれた時点でユーザーによる設定の変更を元のファイルに保存します。

このクラスをアプリケーション実行時に生成して設定を読み込み、終了時に保存します。

後日、設定の一部について任意の場所で読み書きする必要が生まれました。
そこであなたはこのクラスを生成し、変更を保存する事に決めました。

アプリケーションの起動時と終了時、任意の時と場所、ソース中ではこの二カ所でこのクラスが使われています。

そうすると、任意の場所で保存した設定は、アプリケーション終了時に上書きされてしまいます。
あなたは、なぜ変更した設定が保存されないのか悩み、数時間をバグ取りに費やしました。

シングルトンはこのような時に使います。何度インスタンスを取得してもそれは最初の物と同じものなので競合が起こりません。
シングルトンはインスタンスを一つしか作らないデザインではなく、いつでも同じインスタンスを返すデザインです。

投稿2017/04/22 22:00

Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

自分の書き方はシングルトンパターンなのか

シングルトンパターンではありません。

あなたが実装したクラスAがあるとして、それを利用する側(この場合は main関数)が絶対にインスタンスをひとつしか作ることができない場合に、クラスAはシングルトンパターンで実装されていると言えます。

今の状況は、たまたまインスタンスをひとつ作っているだけです。

投稿2017/04/22 21:12

koko_u

総合スコア936

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

_Victorique__

2017/04/22 21:14

捕捉にも書きましたが、一つしか作らなくて済むような書き方をしているという点ではシングルトンと同じと言えますか?
koko_u

2017/04/22 21:21

私には「一つしか作らなくて済むような書き方」がされているようには見えません。 すべてのコードを自分ひとりで作成している場合、クラスが「一つしか作らなくて済むように実装されている」ことと、「今作成したプログラムではクラスAのインスタンスは一つだけである」ことの差がわかり辛いかもしれません。 あなたが実装したクラスAを私が利用するとして、私がどのように頑張ってもクラスAのインスタンスをひとつしか作成できない場合に初めて「クラスAがシングルトンパターンで実装されている」と言えます。
_Victorique__

2017/04/22 21:28

では、私がそういう意図で作ったとして、それはシングルトンの意図と変わりないということでよろしいのですか? 他人が使う場合には2つ以上作れてしまいますが 本質という意味ではそういうことで良いのですか? 私は素人ですのですごく変な質問かもしれません、ごめんなさい
koko_u

2017/04/22 22:12

あなたが「クラスAのインスタンスは一つしか作らない」と考えていたとして、それがコードとして(クラスAの実装として)表現できていなければいけません。 現実世界にはドキュメントに「このクラスは複数のインスタンスを作成した場合、正常に動作しません」と公言し、利用者側に注意深くコードを書くことを強要するライブラリも存在しています。あまつさえ、ドキュメントにすら記載されていないものもあります。 将来そのようなライブラリに遭遇した時にシングルトンパターンの必要性を知るでしょう。
guest

0

「世界に一つだけのインスタンス」がシングルトンであるなら、
僕は「世界に一つだけ」であることをコードで保証します。たとえば:

C++

1class Singleton { 2private: 3 Singleton(); // privateなのでSingleton以外誰も作れない 4 ~Singleton(); 5public: 6 static Singleton* instance(); 7}; 8 9Singleton* Singleton::instance() { 10 // 何度呼ばれても同じものを返す 11 static Singleton only_one; 12 return &only_one; 13} 14 15int main() { 16 Singleton* obj = Singleton::instance(); 17 sub(): 18 ... 19} 20 21void sub() { 22 Singleton* obj = Singleton::instance(); 23 // objは唯一のインスタンスなので引数で引き渡す必要も 24 // グローバル変数である必要もない 25}

投稿2017/04/22 21:05

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

  • 逆引きカタログ Singleton

http://www.nulab.co.jp/designPatterns/designPatterns2/designPatterns2-1.html

...
シングルトンパターンの特徴は、シングルトンクラスのオブジェクト生成を、シングルトンクラス自身が提供するオブジェクト生成用メソッドで行うことです
...

質問文にあるコードは、シングルトンパターンではありません。

呼び出されるクラス側でインスタンスが1つになるような仕組みを用意するのが、シングルトンパターンです。
呼び出す側がどのようにインスタンス生成をしているかは関係ありません。

質問文のコードは、インスタンス生成をクラスごとに1度だけ呼んでいるというだけです。

投稿2017/04/22 23:45

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

シングルトンとは、プログラムの文法レベルでインスタンスを一つのみに制限するものです。ローカルルールを作ることでインスタンスを一つのみに制限してもシングルトンとは言いません。

投稿2017/04/23 03:20

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問