1

他の多くのクラスがGuiのメソッドを使用する必要があり、Guiのインスタンスは常に1つだけであるため、シングルトンであるGuiクラスがあります。

また、Singleton である Player クラス (Audioplayer のようなもの) もあります。

Gui を起動するときに、プレーヤーに現在のステータスを取得して (これにより、プレーヤーの新しいインスタンスが作成されます)、Gui に表示するように指示します。したがって、Gui のコンストラクターがまだ終了していないため、プレイヤーは Gui の新しいインスタンスを作成します。

したがって、これは無限の再帰を作成します。Singletons パターンを維持したいと思います。コンストラクターがまだ終了していなくても、getInstance() のインスタンスを「null」以外に設定する方法はありますか?

ありがとう

4

4 に答える 4

2

おそらく、シングルトン パターンは完全に避けるでしょう。あなたが発見したように、作成ライフサイクルの制御が困難になります。

代わりに、 を作成しGuiManager、 を作成してGui、それについて知る必要がある適切なコンポーネントに挿入します。これは制御の反転(または依存性注入) と呼ばれ、グローバル状態の必要性を回避します。利点には、テストが容易になること (周囲のフレームワークがオブジェクトのライフサイクルを制御するため) が含まれ、これらのオブジェクトの作成は予測可能です。

于 2013-03-14T15:19:57.807 に答える
0

この再帰は、より一般的な設計上の問題の兆候です。確かに、コンストラクター内からインスタンス参照を「リーク」するか、後で呼び出す初期化メソッドに「構築」を延期することで解決を試みることができますが (おそらく遅延)、これはお勧めしません1

GUIPlayer クラスがシングルトンである必要があり、お互いを認識しなければならないのはなぜですか? あるオブジェクトにグローバルにアクセスできる方が「便利だ」以外に理由はありますか? 利便性が重要ではないというわけではありませんが、通常、設計を決定する唯一の理由にはなりません。

Player と GUI の 2 つのインスタンスが同時に存在できないという本当の理由はないため、シングルトンをすべて削除することをお勧めします。もちろん、プログラムにはそれぞれ 1 つしかないでしょうが、それはシングルトンの目的ではありません。

また、依存関係は一方向のみにする必要があります。他者なしに存在できるものと存在できないものについて考えてみてください。おそらく GUI のない Player を想像できるので、GUI は Player に依存するべきだと思いますが、Player のない GUI はまったく意味がありません。したがって、最初に Player を構築し、次に GUI を構築して、それが動作する Player インスタンスに渡します。Player 内のどこからでも GUI インスタンスにアクセスする必要があると思われる場合は、設計を再考し、それらのオブジェクトをより独立させるようにしてください。これは通常、Observer パターンを使用して行うことができ、GUI に変更/アクション/発生したものをリッスンさせます。この方法では、アプリケーション コードは GUI についてまったく認識しません。ただし、GUI 内では、GUI のインスタンスを好きなだけ渡すことができます。

'Manager' オブジェクトまたは Factory パターンを導入するというアイデアについて: それは役に立つかもしれませんが、それがなくても上で述べたことをすべて行うことができ、それでもまともな設計を維持できます。「マネージャー」クラスはあまりにも多くのことを行う傾向があり、通常は変装したシングルトンのようなものであるため、私は通常、「マネージャー」クラスに反対します。ただし、ファクトリは便利な場合がありますが、それは、たとえば、さまざまな種類の GUI を後で実装できるようにするなど、実際の構造をその使用法から切り離したい場合に限られます。

したがって、単純な実装は次のようになります。

public static void main(...) {
    Player player = new Player();
    // maybe some other stuff to configure/set up the player

    GUI gui = new GUI(player);
    gui.show(); // or something similar
}

ファクトリを使用したい場合は、もちろんnew ...式を、以前に取得する必要があったファクトリへの呼び出しに置き換えることができます。

1 なぜ?たとえば、GUI の構築に成功したものの、後で初期化に失敗した場合 (例: 例外がスローされた場合) はどうなるでしょうか? この「無効な」状態を、既に GUI インスタンスを取得しているすべてのオブジェクトに伝える何らかの方法が必要です。また、GUI インスタンスを初期化する前に誰も使用しないようにする必要があります。

于 2013-03-14T15:25:43.153 に答える
0

初期化関数を作成する

public class Gui
{
    public static Gui instance;
    public static Gui getInstance()
    {
        if(instance == null)
        {    
            instance = new Gui();
            instance.initialize();
        }
        return instance;        
    }

    private Gui()
    {

    }

    private initialize()
    {
        // do constructor work here
    }
}
于 2013-03-14T15:22:14.077 に答える
0

静的初期化ブロックを使用します。これは、クラスが構築されているときに呼び出されます。オブジェクトが作成されているときではありません。一度だけ呼び出されます。続きを見る

于 2013-03-14T15:22:26.923 に答える