1

UI にボタン リスナーを追加するときに、2 つの異なるスタイルに遭遇しました。例として SWT を使用します。それにもかかわらず、J2ME、Flash Actionscript でも同様のコードを見ました。

スタイル 1:

    b1.addSelectionListener(new SelectionListener()
    {
        public void widgetSelected(SelectionEvent e)
        {
            System.out.println("b1: ");
        }

        public void widgetDefaultSelected(SelectionEvent e)
        {
            System.out.println("Default selection");
        }
    });

    b2.addSelectionListener(new SelectionListener()
    {
        public void widgetSelected(SelectionEvent e)
        {
            System.out.println("b2: ");
        }

        public void widgetDefaultSelected(SelectionEvent e)
        {
            System.out.println("Default selection");
        }
    });

スタイル 2:

    b1.addSelectionListener(this);
    b2.addSelectionListener(this);

public void widgetSelected(SelectionEvent e)
{
    if (e.getSource() == b1)
    {
        System.out.println(b1);
    } 
    else if (e.getSource() == b2)
    {
        System.out.println(b2);
    }

}

public void widgetDefaultSelected(SelectionEvent e)
{
    System.out.println("Default selection");
}

個人的には、マウス イベントを一元的に処理できる 2 番目のスタイルを好みます。どのスタイルが好きですか? なぜ?

4

3 に答える 3

2

私は一般的に2番目のスタイルが嫌いです。それは、2つのボタン間、およびそれらのコンテナーとの結合を作成するためです。

B1とB2の機能が独立している場合、B1はB2について何も知らないはずであり、その逆も同様です。イベントハンドラーを共有することで、無駄なチェックを行うだけでなく、この独立性を破ることになります。彼らは今、彼らの取り扱いを共有しています。

さらに、オプション2を選択することで、B1、B2、および処理メカニズムを備えたコンテナーの3つのクラスを結合しました。一方、オプション1に従った場合、B1はそのパーソナルハンドラーに結合され、B2はそれ自体のパーソナルハンドラーに結合され、コンテナーはどちらのハンドラーについても何も知る必要がありません。

実際、オプション#2に従うことで、コンテナーに別の責任を与えることになります。コンテナーはイベントルーティングを実行します。ツールキットはすでにイベントルーティングを実行しています。クリックすると、正しいイベントハンドラーが呼び出されます。このオプションを使用すると、車輪の再発明を行うことになります。

各ボタンの処理が十分に複雑な場合は、ボタンの2つのサブクラスを作成し、各サブクラスに独自のリスナーをインストールさせるのが理にかなっている場合があります。次に、コンテナはボタンをインスタンス化するだけで、イベントを処理するためのコードを実際に含める必要はありません(匿名クラスとしても)。

イベント処理を一元化したいという気持ちを理解していることに注意してください。ただし、それはマイクロマネジメントです。GUIプログラミングは大変で退屈です。イベント処理は、GUIプログラミングで最も厄介なことの1つです。これは、自分でルーティングして管理する必要がないことについて、最初に満足すべきことの1つです。ツールキットよりもうまく管理できる説得力のある状況はほとんどありません。

于 2009-07-07T02:45:48.000 に答える
0

ウリからの回答は、アクションをリスナーと一致させることについてのいくつかのアイデアを私に与えました。最初のアプローチの修正版が出ました。

    private Map<Control, ICommand> commandMap = new HashMap<Control, ICommand>();
    private HelloCommand helloCommand = new HelloCommand();
    private WorldCommand worldCommand = new WorldCommand();

    protected Control createContents(Composite parent)
    { ...
            b1.addListener(this);
            b2.addListener(this);
        commandMap.put(b1, helloCommand);
        commandMap.put(b2, worldCommand);   
    }

    public void widgetSelected(SelectionEvent e)
    {
        ICommand command = commandMap.get(e.getSource());
        command.execute();
    }

リスナークラスを作成する代わりに、コマンドクラスを作成するのではなく、一連のクラスを作成するようです。

通常、コントローラークラスはビュークラスとモーダルクラスを制御できます。ただし、この場合、内部クラスにしない限り、ビューコンポーネントに直接アクセスすることはできません。個々のリスナークラスのアプローチにも同じことが言えると思います。これに関する解決策はありますか?

于 2009-07-07T05:01:41.590 に答える
0

私の意見では、これは「場合による」というのが得られる最良の答えの 1 つです。手早く汚いことをしているなら、最初のほうが速くて簡単です。実際のアプリケーションを開発している場合は、2 番目に購入する関心の分離を評価することになります (ただし、ActionListener のものを独自のクラス全体で見たいと思うでしょう)。

少し前に Swing を学んでいたときに見た Swing の入門資料のほとんどすべてが、2 番目のアプローチを採用していました。

最初の方法には、コードの周りにリスナーが分散するという欠点がありますが、一般的に、特定の要素を処理するリスナーを見つけやすくなり、はるかに柔軟になる可能性があります。要素が 2 つ以上ある場合は、巨大な if-else if ブロックを実行するよりもはるかに見苦しくありません。

しかし、2 つ目はコードをより明確に分離します。リスナーはコントローラー ロジックであり、ビュー (GUI) はリスナーが何をするかを気にする必要はありません。また、コントローラー ロジックも一元化されます。何かを変更する必要がある場合は、すべてそこにあります。Web アプリケーションのプログラミングを行う場合、2 番目の方法はよりなじみ深いものになります。

そうは言っても、それは本当に状況に帰着します。いくつかのアクションしかない小さなアプリケーションを開発している場合、どのルートをたどればよいでしょうか? 最初。最初はより高速でクリーンであり、要素とアクションをコードで結び付けます。これにより、少なくとも最初は、保守にかかる労力が少なくて済みます。ただし、より大きなアプリケーションを開発している場合はどうなりますか? ActionListener である別のクラスを作成し、それを専用コントローラーにします。長い目で見れば、それはよりクリーンであり、どんな実際のサイズのアプリケーションでも、長い目で見れば満足するでしょう。

于 2009-07-07T03:23:48.780 に答える