1

私のプログラムには、フィールドに同じクラスを持つフィールドを持つ無限の再帰があります。彼らはシングルトンですが、これはそれらを構築しない原因とはなりません。ところで、私はプログラムを書いたが、実際にフェイズ配列を削除することはできない。無限再帰合成クラス

abstract class Phase{ 
    protected String phaseName; 
    protected char[] keys; 
    protected String[] commands; 
    protected Phase[] phases; 
    protected StringBuilder pattern; 

} 

class RemotePhase extends Phase{ 
    private static RemotePhase remotePhase; 

    protected RemotePhase(){ 
    phaseName="Remote."; 
    commands=new String[]{"Lock/unlock windows", "Toggle door", "Select dog menu"}; 
    setPattern(); 

    //Just below here starts an infinite loop 
    phases=new Phase[]{FixWindows.getFixWindows(), ToggleDoor.getToggleDoor(), SelectDogPhase.getSelectDogPhase()}; 

    } 

    public static RemotePhase getRemotePhase(){ 
    if(remotePhase==null){ 
     remotePhase=new RemotePhase(); 
    } 
    return remotePhase; 
    } 
} 

final class FixWindows extends Phase{ 
    private static FixWindows windows; 
    private RemotePhase remotePhase; 

    private FixWindows(){ 

    //execution keeps coming here as FixWindows object is never constructed 
    remotePhase=RemotePhase.getRemotePhase(); 

    } 

    public static FixWindows getFixWindows(){ 
    if(windows==null){ 
     windows=new FixWindows(); 
    } 
    return windows; 
    } 
} 

私はRemotePhase静的クラスを作成しようとしているとFixWindowsはメンバーのためにそれを使用しますが、私は抽象クラスの非静的メソッドをオーバーライドしようとすると、非静的コンテキストにおけるFixWindowsからそれらを呼び出そうとエラーに走りました。私はそれを静的にしたくないのですが、私はRemotePhaseを参照するために追加のクラスを作る必要があるからです。

これを行う方法はありますが、ありがとう

+2

のための同じを使用することができ、FixWindowsためにこのアイデアを示しています。 – Dici

+0

'FixWindows'コンストラクタを変更し、' RemotePhase'(this)を渡して 'getFixWindows'で構築するか、' getFixWindows'で 'remotePhase'だけを設定します。他のコンストラクタでコンストラクタを呼び出さないようにしてください。あなたの静的メソッドは、そのようなものを設定するのに適しています –

+0

それを表示することができます –

答えて

4

スタティックゲッターでいつでもシングルトンへの参照にアクセスできますが、なぜシングルトンへの参照を保存する必要がありますか?これにより、RemotePhaseへの遅延アクセスがFixWindowsから可能になり、循環依存関係が修正されます。したがって、最もきれいな修正は、単にFixWindowsというコンストラクタ内のゲッターを呼び出さないことです。

final class FixWindows extends Phase{ 
    private static FixWindows windows; 

    private FixWindows(){ 
     // does nothing but preventing external classes to instantiate it 
    } 

    public static synchronized FixWindows getFixWindows(){ 
    if(windows==null){ 
     windows=new FixWindows(); 
    } 
    return windows; 
    } 

    public void methodThatRequiresTheRemotePhase(){ 
    doSomeStuff(RemotePhase.getRemotePhase()); 
    } 
} 

ところで、あなたのコードはスレッドセーフではないことを警告する必要があります。あなたのゲッターは同期する必要があります。

+0

@DannyP。スレッド安全性に関する例と警告で投稿を編集しました – Dici

+0

さて、わかりました。私はフェーズの自動実行を設定するコードを書いていましたが、各相の位相を決定する。 –

+0

あなたは何をしているのか分かりませんが、この多くのシングルトンを2回使うことをお勧めします。通常、シングルトンは主に大規模なリソースのロードやシリアル化を避けるために使用されます(またはスレッドプールなど)が、そのように複雑であるかどうかはわかりません。 – Dici

1

これは、初期化ループを解除する方法に対する回答です。ただし、最初にRemotePhaseへのシングルトン参照を格納する必要はないので、Answer by @Diciはより優れています。

あなたの問題は、シングルトン初期化子が共依存していることです。それを打破する

一つの方法は、初期設定でRemotePhaseが完了する前にRemotePhaseの静的シングルトンフィールドを割り当てることです。これにより、初期化が進行し、シ​​ングルトンオブジェクトが構成されたときに、(部分的に)初期化されたRemotePhaseシングルトンオブジェクトが検出されます。だから、

、このようなチャンスコード:

private RemotePhase() { 
    phaseName = "Remote."; 
    commands = new String[] { "Lock/unlock windows", 
           "Toggle door", 
           "Select dog menu" }; 
    setPattern(); 
} 

private void init() { 
    phases = new Phase[] { FixWindows.getFixWindows(), 
          ToggleDoor.getToggleDoor(), 
          SelectDogPhase.getSelectDogPhase() }; 
} 

public static RemotePhase getRemotePhase() { 
    if (remotePhase == null) { 
     remotePhase = new RemotePhase(); // assigns partially initialized object 
     remotePhase.init();    // completes initialization 
    } 
    return remotePhase; 
} 
0

あなたは別のものでコンストラクタを呼び出すことは避けてください。代わりにセッターを使うことができます。

私はあなたがそれは無限再帰ではなく、無限ループだ他のサブクラス

abstract class Phase{ 
    protected String phaseName; 
    protected char[] keys; 
    protected String[] commands; 
    protected Phase[] phases; 
    protected StringBuilder pattern; 

} 

class RemotePhase extends Phase{ 
    private static RemotePhase remotePhase; 

    protected RemotePhase(){ 
    phaseName="Remote."; 
    commands=new String[]{"Lock/unlock windows", "Toggle door", "Select dog menu"}; 
    setPattern(); 

    //Just below here starts an infinite loop 
    phases=new Phase[]{FixWindows.getFixWindows(this), ToggleDoor.getToggleDoor(), SelectDogPhase.getSelectDogPhase()}; 

    } 

    public static RemotePhase getRemotePhase(){ 
    if(remotePhase==null){ 
     remotePhase=new RemotePhase(); 
    } 
    return remotePhase; 
    } 
} 

final class FixWindows extends Phase{ 
    private static FixWindows windows; 
    private RemotePhase remotePhase; 

    private FixWindows(){ 

    //execution keeps coming here as FixWindows object is never constructed 
    //remotePhase=RemotePhase.getRemotePhase(); //shoud be deleted 

    } 

    public static FixWindows getFixWindows(remotePhase){ 
    if(windows==null){ 
     windows=new FixWindows(); 
     windows.setRemotePahse(remotePhase); 
    } 
    return windows; 
    } 
} 
+0

........................ありがとう –

関連する問題