4

ActionListener私はJavaを初めて使用し、プロジェクトにコードを実装するにはどうすればよいか考えていました。私は内部クラスとActionListenerインターフェースの実装を知っていますが、その道を進むと、コードがおそらく必要以上に乱雑に見えるようになります。

ActionCodeGUIを実装および拡張する別のクラスを作成ActionListenerしますか、それともどのような道を提案しますか、またその理由は何ですか?

それについてのあなたのベストプラクティスのアドバイスは何ですか、そしてそれらのガイドラインはどこにありますか?(JavaDocはActionListenersの基本的な実装を説明しているようですが、大規模/中規模のプロジェクトを編成する方法のモデルがないようです)。

4

3 に答える 3

3

私の意見では、「最善の」アプローチはありません。sun/oracle チュートリアルのコード例でさえ、さまざまな方法でリスナーを実装しています。

私の経験から、良いアプローチは次のとおりです。

  • 匿名の実装を使用する: 人々はこのパターンを知っており、すぐに認識します。物事を行う一般的な方法がある場合、読者がコードを理解するのに役立ちます
  • リスナーのみを処理する特別なメソッドを用意する (例: private void addListeners()): 繰り返しになりますが、これは、誰もがそれを認識し、すべてのロジックを検索する場所を知るのに役立ちます。
  • リスナーをシンプルに保ちます。これは、コードが 5 ~ 10 行未満であることを意味します。より複雑なロジックが必要な場合は、メソッドを呼び出します。
  • リスナーの数を少なくしてください。50 を超えるリスナーが必要な場合は、おそらくビューをリファクタリングする必要があります。10 個以上必要な場合は、リファクタリングを検討できます。

この一般的な点に加えて、常に例外があります。同じ動作のコンポーネントがたくさんある場合と同様に、スイッチ/ケースを使用して汎用リスナーを作成できます。(典型的な例: 電卓のボタンまたはメニュー ボタン)。
または、複数のコンポーネントに同じロジックがある場合は、特定のクラスを使用できます。
等々。

Sun/Oracle のチュートリアルにいくつかの例があるため、言及しておきます。 ビュー クラス自体でリスナー インターフェイスを実装することは避けてください。リスナーが 1 つしかない場合はこれで問題ありませんが、複数のソースからの複数のイベントが異なる動作をする場合は、ほとんどの場合ひどいものになります。

于 2012-12-19T00:21:58.343 に答える
1

コードのスタイルは個人の好みの問題かもしれませんが、現代の文献ではそれ以上のものであることが示唆されています。きれいなコードのクラスに関する章でその方法を説明しましょう。

クラスは小さくあるべきです!

クラスの第一のルールは、クラスは小さくあるべきだということです。クラスの 2 番目のルールは、それよりも小さくする必要があるということです。いいえ、関数の章とまったく同じテキストを繰り返すつもりはありません。しかし、関数と同様に、クラスの設計に関しては、より小さくすることが基本的な規則です。関数と同様に、私たちの当面の質問は常に「どのくらい小さいのですか?」です。関数では、物理的な行を数えることでサイズを測定しました。クラスでは、別の尺度を使用します。私たちは責任を数えます...

単一責任の原則 (SRP) では、クラスまたはモジュールには、変更する理由が 1 つだけある必要があると述べています。この原則は、責任の定義とクラス サイズのガイドラインの両方を提供します。クラスの責任は 1 つである必要があります。変更する理由は 1 つです...

問題は、私たちの多くが、プログラムが機能したら終わりだと考えていることです。整理整頓と清潔さという他の関心事に切り替えることができません。前に戻って過剰なクラスを単一の責任を持つ分離されたユニットに分割するのではなく、次の問題に進みます。同時に、多くの開発者は、小規模で単一目的のクラスが多数あると、全体像を理解するのが難しくなるのではないかと懸念しています。彼らは、より大きな仕事がどのように達成されるかを理解するために、クラスからクラスへと移動しなければならないことを懸念しています. ただし、多くの小さなクラスを含むシステムには、いくつかの大きなクラスを含むシステムほど可動部分はありません。いくつかの大規模なクラスを備えたシステムで学ぶことは同じくらいたくさんあります. 問題は、ツールをツールボックスに整理し、それぞれに適切に定義され、適切にラベル付けされたコンポーネントを含む多くの小さな引き出しが必要かどうかです。それとも、すべてを放り込むだけのいくつかの引き出しが必要ですか?

大規模なシステムにはすべて、大量のロジックと複雑さが含まれます。このような複雑性を管理する主な目標は、開発者がどこを見れば問題を見つけられるかを把握し、直接影響を受ける複雑性のみをいつでも理解できるように組織化することです。対照的に、大規模で多目的なクラスを含むシステムでは、今すぐに知る必要のない多くのことを処理する必要があるため、常に妨げになります。以前の強調点をもう一度言い直すと、私たちはシステムをいくつかの大きなクラスではなく、多くの小さなクラスで構成することを望んでいます。小規模な各クラスは、単一の責任をカプセル化し、変更する理由が 1 つあり、他のいくつかのクラスと協力して、望ましいシステム動作を実現します。

したがって、これらのヒューリスティックに基づいて、ネストされたクラスは SRP を破ります。それらはほとんど起こらないはずです。代わりに、GUI クラスに、登録する ActionListeners のインスタンス メンバーを含めます。リスナーを別の *.listener パッケージに保持します。インターフェースを使用して、効果的と思われる場合はいつでも交換可能 (戦略パターン) にします。

于 2012-12-19T00:15:51.420 に答える
0

Java と Swing は、Listener や Action などの多くの小さなオブジェクトを奨励しています。決まり文句がたくさんありますが、それが Java のやり方です。戦うメリットは少ない。

匿名リスナーをインラインで作成するのはかなり簡単です。

JButton okButton = new JButton("OK");
okButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        ok();
    }
});

ただし、同じアクションをメニューとボタンに割り当てるなど、アクションを再利用する必要があることがよくあります。これらをメイン アプリケーション ウィンドウに内部クラスとして配置できます。

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;


public class MainWindow extends JFrame {

    ZapAction zapAction;

    public MainWindow() {

        setSize(new Dimension(200,200));

        zapAction = new ZapAction();

        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("Foo");
        menu.add(new JMenuItem(zapAction));
        menuBar.add(menu);
        setJMenuBar(menuBar);

        JButton zapButton = new JButton(zapAction);

        add(zapButton);
    }

    public void zap() {
        // do some zapping
        System.out.println("Zap!");
        // maybe we're all done zapping?
        zapAction.setEnabled(isZappingPossible());
    }

    public boolean isZappingPossible() {
        // determine if there's zapping to be done
        return Math.random() < 0.9;
    }

    class ZapAction extends AbstractAction {
        public ZapAction() {
            super("Zap");
            putValue(AbstractAction.SHORT_DESCRIPTION, "Zap something");
            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(
                KeyEvent.VK_Z, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
            putValue(AbstractAction.SMALL_ICON, 
                new ImageIcon(MainWindow.class.getResource("/icons/zap.png")));
            setEnabled(true);
        }
        public void actionPerformed(ActionEvent e) {
            zap();
        }
    }
}

public class Zap {
    public static void main(String[] args) {
        MainWindow mainWindow = new MainWindow();
        mainWindow.setVisible(true);
    }
}

ここでZapActionは、package-private 可視性です。すべての UI コードを独自のパッケージに入れました (たとえばorg.myorg.myproject.ui)。したがって、すべての UI オブジェクトがアクションにアクセスできます。

複雑な Swing アプリでは、UI ファサード レイヤーを作成するところまで行きました。これは、アクションと、それらをさまざまなコントロールに接続するすべてのコードのための適切な場所になります。また、外部コードが UI と対話するための便利な場所にもなり、UI コードがコア アプリケーション コードから分離されます。

于 2012-12-19T02:05:23.307 に答える