8

Java でリスナーを使用するためのベスト プラクティスは何かについて議論がありました。リスナー ロジックを匿名クラスにとどめるべきか、それとも別のメソッドにすべきか、たとえば次のようになります。

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // code here
    }
});

また

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        buttonPressed();
    }
});

private void buttonPressed() {
    // code here
}

可読性と保守性の観点から推奨される方法はどれですか? コードをリスナー内に保持し、大きくなりすぎた場合にのみ内部クラスにすることを好みます。ここでは、コードが他のどこにも複製されていないと仮定します。

ありがとうございました。

4

6 に答える 6

4

私の自主ルールは次のとおりです。

  1. リスナーに 2 つ以上のメソッドがある場合は、名前付きクラスを作成します。
  2. リスナーが 10 行を超える場合は、名前付きクラスを作成します。

非常にシンプルで、従うのが簡単で、多かれ少なかれ読みやすいコードを生成します。しかし、あなたの例が示していることを考えたことさえなかったことを認めなければなりません。

于 2011-01-15T19:23:22.340 に答える
2

この質問は、ここで部分的に回答されています。

リスナーのためのより良い練習はありますか

また、2 つの理由で匿名の方法が好きではありません
。1) コードを簡単に再利用できないため、しばらくするとコードが重複していることに気付くかもしれません。 .. 個人的な好み)。5 行から 10 行を超える行を実行している場合、匿名の内部クラスはお勧めできません (2 行を超えると多すぎると思います)。

于 2011-01-15T19:24:40.697 に答える
1

個人的な意見としては「場合による」です。リスナーが単一のコンポーネントにのみ追加され、非常に単純で、GUI の不可欠な部分である場合は、匿名の内部クラスがうまく機能します。リスナーが複雑で、複数のコンポーネントに追加され、独自の個別の状態を持つ場合は、個別のスタンドアロン クラスの方が適しています。間にあるのはプライベート内部クラスです。HTH。

編集:私の悪い。私は別の質問に答えていました-リスナーに別のスタンドアロンクラスを使用するかどうか。anon内部クラスコードをインラインとメソッド内のどちらに保持するかについては、他のポスターに同意します。リスナーコードのサイズと複雑さに依存します。

于 2011-01-15T19:24:25.117 に答える
1

buttonPressed()匿名の内部クラス以外からメソッドにアクセスする必要がある場合は、メソッドを使用します。それ以外の場合は、単にコードを 内に配置しますactionPerformed()

于 2011-01-15T19:26:09.800 に答える
1

私の個人的な経験では、MVC パターンに従うのが最善です。このように、モデルを表す別のクラスがあり、関連するすべてのアクション、アクション リスナーなどを作成します。アクションは、コンストラクターでインスタンス化される最終クラス フィールドとして表されることが望ましいです。

例えば:

public class Model {
    private final Action buttonAction;
    ...

    public Model(final IController controller) {
       buttonAction = createButtonAction(controller);
       ...
    }

    private Action createButtonAction(final IController controller) {
        Action action = new Action("Action") {
            public void actionPerformed(final ActionEvent e) {
                // do the required action with long running ones on a separate Thread
                controller.run();
            }
        };
        action.set...// other initialisation such as icon etc
        ...
        return action;
    }
    ...

    public Action getButtonAction() {
        return buttonAction;
    }
}

ビューは、実際のボタンのインスタンス化が行われるコンストラクター パラメーターとしてモデルを受け取る別のクラスによっても表されます。例えば:

public class View extends JPanel {
    public View(final Model model) {
       ...
       JButton button = new JButton(model.getButtonAction();
       ...
    }
}

このアプローチでは、actionPerformed のロジックを匿名クラスの一部として実装すると非常に便利です。すべてのロジックはコントローラにカプセル化されているため、アクションはボタンのモデルとして使用されるコントローラ呼び出しのラッパーとして実際に機能します。

于 2011-01-15T19:27:56.953 に答える
0

はい、それはあなたがしようとしていることに大きく依存します。匿名の内部クラスは、2 つの神話のために悪評を得ていると思います。1 つは、匿名コードを再利用できないことです。2 つ目は、メモリ リークです。しかし、これらは簡単なアプローチで簡単に修正できます。インスタンスへの参照を保存します。コードを共有するには、匿名の内部クラスへの参照を作成するだけです。

Action action = new AbstractAction("Open") {...};
JButton button = new JButton( action );
JMenuItem menuItem = new JMenuItem( action );
panel.getActionMap().put("openFile", action );

そのアクションを複数のコンポーネントで再利用できるようになりました。後のメモリリークの問題については、その参照を使用して登録を解除できます。または、2番目のより簡単なオプションはWeakListenersです。WeakListeners には、作成後に管理する必要があまりないという利点があります。

スタイルに関しては、Anonymous リスナーは非常に便利で、コードを 1 つのメソッド (invokeLater、executeInBackground など) に保持するため、Swing でスレッド化を処理するときに読みやすい場合があります。リスナーがインスタンスメソッドにデリゲートするとき、リスナーの前に何が起こったのかを読むことができないコードと、リスナーに関連付けられたロジックを1つの画面で分離すると思います。それらは分離する傾向があり、追跡するのが難しくなります。

注意すべきことは、ActionMaps を使用すると、ほとんどのメモリ リークがキーボード リスニングに関連して解消されることです。残念ながら、フォーカス リスナーや中央システムに登録されているリスナーなどは依然として問題です。(ここでも、WeakListeners は優れています)。また、すべてのコンポーネントでアクションを保持する場所がすでにあるため、それを保持するために追加のインスタンス変数を作成する必要はありません。2 つのコンポーネント (メニュー バーとコントロールなど) で再利用する必要がある場合は、別のクラスを作成します。

于 2011-01-16T01:44:32.720 に答える