web-dev-qa-db-ja.com

他のものがそれを参照するときにオブジェクトを削除する方法(そしてコードを相互依存性でいっぱいにしない方法)

状況:

私のプログラムでは、キューのリストがあります。特定の時間にキューを呼び出すために、トリガーと呼ばれるオブジェクトがあります。キューには、とりわけ、「発砲」される(アクションを実行させる)ための多くのパブリックメソッドがあります。トリガーは、アクティブ化されたときにキューを「発射」します。 Cueへの参照を取得し、Cue.fire()を呼び出すことでこれを行います。トリガーはすべて、トリガーを配列リストに保持するTriggerManagerというクラスに格納されます。キューは相互にリンクされたリストの一部です。つまり、夏場では、トリガーはキューについて知っていますが、キューはトリガーについて知りません。トリガーは特定の時間にキューを呼び出します。

問題:

リンクされたリストからキューを削除しても、それが参照されているトリガーがあるため、「生きている」/ガベージコレクションされていません。自然なことはトリガーを削除することですが、それは解決する必要がある多くの問題を作成します:

主なものは次のとおりです。キューはそれを参照するトリガーを認識していないため、削除するにはどうすればよいですか。 (特に、TriggerManagerクラスによって参照されるため)。キューをトリガーに依存せず、トリガーをトリガートリガーに依存せずにこれを行う方法が必要ですORキューはトリガーマネージャーに依存しています。コードが複雑になり、追跡が困難になります)

質問:コードを管理しやすい状態に保ちながら問題を解決する解決策はありますか?私のデザインには本質的に欠陥がありますか?もしそうなら、どうすれば修正できますか?

4
sinθ

リンクされたリストは、実際にはここでは役に立ちません。それをCueManagerに置き換えます

  1. キューのリストが含まれています
  2. キューをそれぞれのトリガーにマップします

CueManagerは、キューのライフサイクルを制御する必要があります。キューを追加し、それぞれのトリガーから削除します。

interface CueManager {
  public addCueToTrigger(Cue, Trigger);
  public removeCueFromTrigger(Cue, Trigger);
  public deleteCue(Cue);
}
1
Matthew Flynn

私が最初に考えたのは、何らかのパブリッシュ/サブスクライブモデルやコールバックですが、双方向参照を回避するという要件に違反しています。

代わりの方法は、「c​​ueIsAlive」フラグをキューに追加することです。コンストラクターでtrueに設定し、RemoveFromLinkedList()呼び出しでfalseに設定して、Cue.Fire()メソッドで使用します。

public void Fire() {
    if (this.cueIsAlive) {
        ... execute Fire code ...
    }
}

これがゾンビオブジェクトと見なされるかどうかはわかりませんが、基本的な考え方は、ガベージコレクションが実行されるまで無害にすることです。

1
Dan Pichelman