イベントリスナーの実装
Javaでは、イベントリスナーを実装するのに3つの方法があります。そしてそれぞれ3つの方法には、 長所と短所があります。ソースの可読性を高める上では、1つの方法を全体を通して使うべきですが、 あくまで個人的なプログラムであれば、多少読みづらくても楽に作れた方がいいこともあります。 ここでは3種類のイベントリスナーの実装方法について説明します。
方法1
1つ目の方法はアプリケーションのコンテナクラスにインタフェースを実装する方法です。 恐らくこれが最もオーソドックスなものだと思います。以下のソースを見てください。

			
import java.awt.*;
import java.awt.event.*;

class TestFrame extends Frame implements ActionListener {
    Button button = new Button();
    ...
    public void TestFrame {
        button.addActionListener(this);
        ...
    }
	
    public void actionPerformed(ActionEvent e) {
        ...
    } 
}

コンテナであるFrameクラスのサブクラスにActionListenerインタフェースを実装しています。 この方法だと、このコンテナがイベントリスナーを実装していることが明確になります。 クラス宣言を見ただけで、何らかのイベントを実装しているんだと分かりますね。

ただし、この方法には短所もあります。それは、例えばいくつものボタンを使って いくつもの処理を行う際には、actionPerformedメソッドの中でActionEvent#getSourceメソッドを 使ってどのボタンが押されたのか調べることになりますが、ボタンの数が多いとこのメソッドが肥大しがちです。 そうなると当然読みづらいものになってしまいます。

そこで、それぞれのボタンに対して別のリスナーを登録する方法があります。 それが2番目の方法です。
方法2
2つ目の方法は無名内部クラスを使う方法です。以下のソースを見てください。

			
import java.awt.*;
import java.awt.event.*;

class TestFrame extends Frame {
    Button button = new Button();
    ...
    public void TestFrame {
        button.addActionListener(
            new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    ...
                }
            }
        );
        ...
    }
}

この方法だと、それぞれのコンポネーントごとに実装を分離できます。 そのため、「このボタンはこういう処理をするんだな」という事がより明確になります。 方法1を使うとactionPerformedメソッドが大きくなりすぎる場合は有効かも知れません。 ただし、見てもらえれば分かるように、明らかに全体のプログラムは大きくなり、 また、それぞれのコンポーネントに上のような記述を施すのは面倒です。

ところで、方法1、方法2は両方とも、ActionListenerという名前のインタフェースを実装しています。 インタフェースを実装するということは、そのインタフェースで定義されている抽象メソッドを 全て実装しなければならないということです。 上の例ではActionListenerインタフェースなので、定義すべきメソッドはactionPerformed1つだけ でしたが、WindowListenerや、MouseListenerではもっとたくさんのメソッドが定義されているので、 たとえその内1つのメソッドしか使わなくても、すべてのメソッドを実装しなければなりません (具体的には、空のメソッドとなります。ああ、めんどくさい。)。これは正直面倒ですし、 メソッドを書くのを忘れてコンパイルエラー、なんてこともよくあります。

そこで、必要なメソッドだけを使ってイベントリスナーを実装できる方法があります。 それが方法3です。
方法3
3つ目の方法ではアダプタクラスを使います。以下のソースを見てください。

			
import java.awt.*;
import java.awt.event.*;

class TestFrame extends Frame {
    ...
    public void TestFrame {
        addMouseListener(
            new MouseAdapter() {
                public void mousePressed(MouseEvent e) {
                    ...
                }
            }
        );
        ...
    }
}

この方法の明らかな長所は、必要なメソッドだけを実装すればいいことです。 上記のMouseAdapterに対応するインタフェースであるMouseListenerでは、5つのメソッドが 抽象メソッドとして定義されているので、5つのメソッド全てを実装しなければなりません。 ところがアダプタクラスを使えば、必要なmousePressedメソッドだけを実装すればいいのです。

この事からも明らかなように、アダプタクラスは抽象クラスです。 インタフェースでは抽象メソッドしか定義できず、それを実装したクラスはすべての抽象メソッドを 実装しなければなりません。けれども抽象クラスでは、抽象メソッドと実装されたメソッドを混在させる ことが可能です。以下はMouseAdapterクラスのコードです(Javadocコメント、コメント、package宣言は 省略しています)。

			
/*MouseAdapter.java*/
public abstract class MouseAdapter implements MouseListener {
    public void mouseClicked(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

上記のように、アダプタクラスでは対応するインタフェースを実装し、デフォルトの処理 (何もしない)を記述することで、そのサブクラスに実装の義務を与えません。 なので、全てのメソッドをオーバーライドする必要はなく、 自分の実装したいメソッドだけをオーバーライドすることが出来ます。

ちなみに、無名内部クラスというのは、implementsやextendsの省略形だと考えることが出来ます。 当然のことですが、インタフェースや抽象クラスは、インスタンスを生成することが出来ないので、 方法2や方法3のコード中の無名内部クラスは、それぞれActionListenerの実装クラスと、 MouseAdapterのサブクラスだと考えられます。