46

つまり、デスクトップアプリケーションの場合。これは一般的な質問であり、一般的な回答のみが必要な場合があります。

4

9 に答える 9

40

静的データメンバーを持つ静的クラス?しかし、誰が気にします。静的データメンバーは、より政治的に正しいパッケージ化を備えた単なるグローバル変数です。

ファッションがあなたの常識を覆すことを許さないでください。単純な古いグローバル変数を使用しても問題はありません。シングルトンパターンは、多くの場合、やり過ぎで入力するのが面倒であり、コードをシングルステップでデバッグする場合は面倒です。

C / C ++を使用していると仮定すると、ヒープからメモリを割り当てるクラスインスタンスであるグローバル変数を使用しないことをお勧めします。それらは、メモリリークをチェックするツールの使用を困難にします。グローバルをポインタとして宣言し、main()の最初で新しく、最後で削除します。

6つのコメントの後で編集:ロギングについて考えてください。アプリのどこからでもログに行を書き込めるようにしたいと思いませんか?そのロギングを行うためにグローバルに目に見えるものがない状態で、どの程度具体的にそれを達成しますか?グローバルに表示したい場合は、先に進んでグローバルに表示します。

于 2008-12-13T14:40:47.183 に答える
21

答えは言語によって異なります。私は最近、多くの一般的な携帯電話で動作する USB スタックを開発している会社の男性に会いました (たとえば、電話がコンピューターと通信できるようにするため)。すべての C プロシージャーは再入可能でなければならないという規則があります。実際には、これが意味することは、グローバル変数の代わりに、各ルーチンに追加のパラメーターを使用することです。パラメータは、ルーチン間で保持する必要がある状態を指します。

私は、状態を抽象化するために常にこの手法を使用しています。例: 写真画像のリーダーの抽象化: リーダーは一度に 1 つのピクセルへのアクセスを提供します。開いているファイル記述子、イメージ内の現在の位置などを認識している必要があります。そのすべての情報は、プライベート C 構造体または C++ クラスのプライベート メンバーに入ります。グローバル変数はありません。外の世界は次のように見えます。

typedef struct Pnmrdr_T *Pnmrdr_T;

struct Pnmrdr_T *Pnmrdr_new(FILE *);
pixel Pnmrdr_get(Pnmrdr_T);
void Pnmrdr_close(Pnmrdr_T);
void Pnmrdr_free(Pnmrdr_T *rp); // frees memory and sets *rp = NULL

このスタイルのプログラミングは、オブジェクト指向メソッドに非常に似ています。

グローバル変数よりも優れているのはなぜですか? 驚きはありません。何か問題が発生したり、機能を追加したりした場合、渡される値はすべて明示的であることを知っています。さらに、多くのモジュールを一緒にプラグインでき、それらの間で明示的に状態を渡さない限り干渉しないことを知っています。携帯電話業界の私の担当者は、この資産は彼の会社にとって非常に大きなものであると言っています。彼らは OEM ソフトウェア企業であり、さまざまな顧客のためにさまざまな部品を簡単に接続できます。

私はこの方法でプログラミングするのが本当に好きです。なぜなら、起こっていることすべてを見ることができ、私のプライベートなデータ構造は詮索好きな目から保護されているからです :-)

于 2008-12-13T19:41:43.313 に答える
10

まず、単一化がグローバルよりも何らかの形で優れている、または受け入れられるふりをすることに意味はありません。シングルトンは、OOPのように見えるようにドレスアップされたグローバルなものです。他の多くの問題が投げ込まれています。

もちろん、代替手段はグローバルデータを持たないことです。クラスがどこかの静的(グローバル)変数にアクセスする代わりに、データをコンストラクターに渡します。はい、コンストラクターにいくつかの引数を追加する必要があることを意味しますが、それは悪いことですか?これにより、クラスの依存関係が明示的になります。コンストラクターでクラスにさまざまなオブジェクトを提供するだけでクラスをテストできますが、グローバルデータに依存している場合は、それらのグローバルがテストに存在する必要があり、面倒です。

同様に、オブジェクトに直接渡されるもの以外にクラスへの魔法の依存関係がないため、簡単にリファクタリングできます。

すべてのオブジェクトが同じグローバルインスタンスと通信する必要がなくなるため、スレッドセーフの管理が容易になります。代わりに、クラスの個別のインスタンスを渡すことができます。

于 2008-12-13T18:24:25.030 に答える
4

シングルトン変数またはグローバル変数が推奨されないかどうかは気にしません。それが最も論理的な実装方法であると思われる場合は、先に進んで使用します。

于 2008-12-13T15:37:17.133 に答える
2

それはあなたが解決しようとしている問題に完全に依存します。この重要な情報はあなたによって省略されました。包括的なソリューションを探しているのなら、それはありません。該当する場合に適用するパターンがあります。

于 2008-12-13T14:48:39.460 に答える
1

グローバルとシングルトンの両方で私が見た最も一般的な懸念は、スレッドを使用するときに悪い動作をするリスクがあるということです。この場合、常に実行スコープを基本単位として使用する必要があります。これは OO プログラミングの強みの 1 つです。オブジェクト メンバーを使用して、関連するすべてのデータを保持することができ、偶発的なスレッドの混乱をほとんど心配する必要はありません。これは、パラメーターを介してデータを渡す必要がある OO 非対応のプログラミング言語とは対照的です。

もう 1 つの一般的な懸念は、組織に関するものです。いつでも読み書きできる大規模なシステムでは、データがどこから来るのかを正確に理解するのは困難です。私の経験では、これはコード自体の問題ではなく、開発者の問題です。難しい問題の例として主にプログラミングの本に登場するような数億行のメガシステムの 1 つに取り組んでいるのでない限り、コードベース全体から特定の項目を合理的に短時間で検索することができます。期間。必要な次のステップは、コードベースを定期的に監査して、グローバル/静的変数が無作為に割り当てられていないことを確認することです。これは多くの開発アプローチにとって忌み嫌われますが、特定のサイズと複雑さのシステムでは、完全に実行可能なソリューションです。

于 2008-12-13T15:50:05.623 に答える
0

グローバルとシングルトンを使用し、すべてが台無しになるのを見た後、私はこの解決策にたどり着きました。

  1. すべてのグローバル変数をクラスのメンバーにします。論理的には、すべてのグローバル変数はアプリケーション (またはシステム) に属します。アプリケーションクラスを作成するだけです。グローバル オブジェクトをプロパティとして定義します。そのため、最初に呼び出されたときに作成されます。

  2. アプリケーション クラスのシングルトンを作成して、グローバルにアクセスできるようにします。これは、コード内の唯一のシングルトンになります。最終的には、Java の system.out または system.in オブジェクトのようなものです。

注:これは非常に古い質問ですが、今でも人気があります。

于 2016-02-23T13:57:00.023 に答える
0

これに対する一般的な解決策は、シングルトン/グローバル変数の代わりに単一インスタンス クラスを使用することです。

アプリケーションは、インスタンスが 1 つだけであることを確認する責任があります。

このソリューションは、人々がクラスをインスタンス化するのを防ぐことができないため(シングルトンではない)、内部クラスでなければならないため、ちょっとひどいです。

ただし、シングルトン パターンに関するすべての宗教戦争についてはあまり気にしません。自分のニーズに合っていると思われる場合は、通常はそれを使用します。

于 2008-12-13T15:32:14.663 に答える
-1

グローバル変数は小さなプログラムでは問題ありませんが、それらが大きくなると、誰かが変更を加えたりバグを修正したりすると、「ああ、このグローバルを設定するだけで問題は解決します」という奇妙な副作用が発生し始めます。

于 2008-12-13T15:47:54.803 に答える