2

シングルトンが嫌われている理由を理解しようとしています。

シングルトン MyClass があるとしましょう:

class MyClass
{
public:
    void doSomething();
    static MyClass* getInstance();
private:
    int whatever;
    static MyClass* myClass;
    MyClass();
};

それを参照するクラスがあります:

void A::B()
{
    ...
    MyClass::getInstance()->doSomething();
}

私が読んだことは、クラス A が MyClass に依存するようになったことです。クラス A を効果的にテストすることは、同時に MyClass をテストすることを意味します。誰でもどこでも MyClass を同時に変更できるため、 A::B() の結果は予測できません。

しかし、なぜグローバルアクセシビリティがこの原因なのですか? 代わりに集計を使用するとどうなるでしょうか? クラス A が MyClass オブジェクトへのポインタまたは参照を持っていて、他のクラスも同じオブジェクトへのポインタまたは参照を持っているとしたら?

class A
{
public:
    void B();
private:
    MyClass* myClass;
};
void A::B()
{
    ...
    myClass->doSomething();
}

他のクラスが同じ myClass オブジェクトを同時に変更しているため、 A::B() がそれに依存しているという同じ問題はありませんか? 問題は、複数の場所で同じものを参照するのは、ほとんど「グローバル状態」のようなものではないでしょうか?

(この質問が以前に投稿されたことは認識していますが、同じオブジェクトへの複数の参照がより優れている理由について、他の誰かが具体的に質問したとは思いません。)

4

1 に答える 1

1

「誰でもどこでも MyClass を同時に変更できます」

これは、ある種のマルチスレッドまたはマルチプロセス環境でのみ可能です。それが懸念事項である場合、2番目の例は良くないように思われます。

グローバル - または呼び出し元のシングルトン - は、マルチスレッド環境では推奨されません。これは、あなたが話している同時アクセスの可能性があるためです。並行性の問題を回避するには、同期メカニズムに対処する必要がありますが、必ずしもそう簡単ではありません。

マルチスレッドがなくても、グローバルはコードの管理、デバッグ、および制御を単純なシステム以上に困難にする傾向があります。

一般に、「集約」は「シングルトン」に代わるものではありません。シングルトンに代わるものは、複数のインスタンスであり、それぞれが特定のスレッド専用であるか、特定のクラスまたはメソッドに対してローカルです-おそらく「集約」とは-それにより、同時実行性と制御/コード管理の問題を回避します。

集約「委任」または「オブジェクト構成」 (このコンテキストでは多かれ少なかれ同義語) は、一般に継承の代替と見なされます基本クラスから機能を継承するよりも、完全に別のクラスを設計する方が望ましいことがよくあります。必要な機能を実行し、呼び出し元のクラスによって参照および制御されます (「ブラック ボックス」の概念)。

継承に関する問題の 1 つは、派生クラスでは不適切な可能性がある基本クラスからの実装と動作を、派生クラスが処理するように強制する傾向があることです。また、必ず実装の詳細を派生クラスに公開することも強制するため、カプセル化に違反します。理想的には、適切に設計されたクラス階層がこの問題を回避しますが、クラス Cat(Animal)、クラス Dog (Animal) などの教科書定義の範囲外のものを扱う場合、そのようなクラス階層を設計することは一般に簡単なことではありません。

于 2013-01-13T02:54:18.523 に答える