IT/자바

Event Handler - 13.4.2 Listener와 Adapter

Beautifulkim 2018. 5. 9. 18:02

출처 : https://blog.naver.com/seektruthyb/150114862640 | 13.4 Event Handler - 13.4.2 Listener와 Adapter|작성자 SeektruthYB


13.4.2 Listener와 Adapter

앞 에서 이미 Listener에 대해서 어느 정도 맛을 보았을 것이다. 여기서는 Listener와 Listener 대신 사용할 수 있는 Adapter에 대해서 알아보자. 일반적으로 이벤트를 처리하는 방법은 Listener를 구현하는 방법과 Adapter를 구현하는 방법으로 나눌 수 있다.

□ 이벤트를 구현하는 방법
◇ Listener를 이용한 구현
◇ Adapter를 이용한 구현

Listener로 구현하는 방법은 앞에서 배운 것과 같이 다음과 같은 과정을 거치게 된다.

□ Listener를 구현하는 방법
◇ Java Doc API에서 해당 Listener를 검색한다.
◇ 해당 Listener의 추상 메서드를 모두 구현한다.
◇ 원하는 컴포넌트에 해당 Listener를 장착한다.

이것은 앞에서 이미 배운 내용이다. 그런데 인터페이스의 추상 메서드를 모두 구현하는 것은 너무나 비합리적이다. 다음과 같은 요구사항이 생길 수도 있다.

□ 요구사항
◇ Listener의 경우 사용하지 않는 추상 메서드까지 모두 구현해야 하는데 필요한 것만 구현할 수는 없을까?

이 러한 기능을 위해서 Listener를 미리 구현해 놓은 Adapter라는 것을 제공하고 있다. 예를 들어 WindowListener를 구현한 Adapter를 WindowAdapter라고 하며, WindowAdapter는 WindowListener의 추상 메서드를 모두 구현한 클래스이다. 다음은 WindowListener 인터페이스의 원형을 보여주고 있다.

▒ WindowListener 인터페이스의 원형

1
2
3
4
5
6
7
8
9
public interface WindowListener{
         void windowClosing(WindowEvent e);
         void windowActivated(WindowEvent e);
         void windowClosed(WindowEvent e);
         void windowDeactivated(WindowEvent e);
         void windowDeiconified(WindowEvent e);
         void windowIconified(WindowEvent e);
         void windowOpened(WindowEvent e);
 }


Adapter 라는 것은 Listener 인터페이스가 정의하고 있는 메서드들을 구현하고 있는 추상 클래스라고 말하였다. 하지만 Adapter의 구현은 비어 있는 구현이다. 특별한 구현 내용이 추가된 것이 아니라 빈 괄호({ })만 붙여둔 구현이다. 빈 괄호도 구현이기 때문에 우리가 Adapter를 사용할 때는 필요한 것만 재정의해서 사용하면 된다. 다음은 WindowAdapter 클래스의 원형을 보여주고 있다.

▒ WindowAdapter 클래스의 원형

1
2
3
4
5
6
7
8
9
public abstract class WindowAdapter implements WindowListener{
         public void windowClosing(WindowEvent e){ }
         public void windowActivated(WindowEvent e){ }
         public void windowClosed(WindowEvent e){ }
         public void windowDeactivated(WindowEvent e){ }
         public void windowDeiconified(WindowEvent e){ }
         public void windowIconified(WindowEvent e){ }
         public void windowOpened(WindowEvent e){ }
 }


☞ 참고

Listener에 대응하는 각각의 Adapter는 모두 Adapter라는 단어로 끝나며, 이 Adapter 클래스들은 모두 추상 클래스들이다. Adapter들은 추상 메서드를 포함하고 있는 것이 아니라 클래스를 선언할 때 단지 abstract로 선언했기 때문에 추상 클래스가 된 것이다. 이러한 추상 클래스는 상속만으로도 완전한 구현이 된다. 이것에 대해서는 5장의 추상 메서드를 참고하기 바란다.



Adapter 클래스들은 이미 해당 Listener 인터페이스의 모든 추상 메서드들을 구현해 놓았기 때문에, Adapter 클래스를 상속받게 되면 그때 그때 필요한 메서드만을 선택적으로 구현해서 사용할 수 있다. 각 Listener에는 각각의 추상 Adapter 클래스가 존재한다. 결과적으로 WindowAdapter는 단순히 WindowListener의 비어 있는 구현에 불과한 것이다. 다음은 이벤트를 처리하는 Listener와 그에 상응하는 Adapter를 나열하고 있다.

▒ 주요 Listener들

1
2
3
4
5
6
7
MouseListener
MouseMotionListener
WindowListener
ComponentListener
ContainerListener
FocusListener
KeyListener


▒ 주요 Adapter들

1
2
3
4
5
6
7
MouseAdapter
MouseMotionAdapter
WindowAdapter
ComponentAdapter
ContainerAdapter
FocusAdapter
KeyAdapter


Listener를 구현하는 방법은 앞에서도 배웠지만 복습하는 의미에서 다시 한번 보자. 다음은 WindowListener를 구현해서 프레임의 종료를 구현하는 예이다.

§ chap13\ListenerFrameMain.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
WindowListener를 구현해서 프레임의 종료를 구현하는 예
**/
import java.awt.*;
import java.awt.event.*;
class ListenerFrame extends Frame implements WindowListener{
    public ListenerFrame(){
        this.addWindowListener(this);
    }
    public void windowClosing(WindowEvent e){
       System.exit(0);
    }
    public void windowActivated(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowOpened(WindowEvent e) {}
}
 
public class ListenerFrameMain{
    public static void main(String[] args){
      Frame f = new ListenerFrame();
      f.setSize(300,100);
      f.setTitle("WindowListener 구현");
      f.setVisible(true);
    }
}
/***
c:\javasrc\chap13>javac ListenerFrameMain.java
c:\javasrc\chap13>java ListenerFrameMain
그림1
 
***/
그림1 



Adapter를 구현하는 방법은 단순하지만 약간 특이한 형태의 구현법을 사용한다. WindowAdapter를 구현하기 위해서는 addWindowListener()의 매개변수 자리에서 직접 구현해서 사용한다.

▒ WindowAdapter를 이용한 구현

1
2
3
4
5
6
7
8
9
10
11
class AdapterFrame extends Frame{
         public AdapterFrame(){
             this.addWindowListener(
                 new WindowAdapter(){
                     public void windowClosing(WindowEvent e){
                         System.exit(0);   
                     }
                 }
             );
         }
 }


WindowAdapter 의 경우 모든 추상 메서드들이 구현된 상태이기 때문에 필요한 메서드만 재정의하는 형식으로 구현해서 사용하면 된다. 대부분의 Adapter들은 위의 방식으로 구현되니 잘 기억해두기 바란다. 다음은 WindowAdapter의 완성된 예이다.

§ chap13\AdapterFrameMain.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
WindowAdpater를 이용한 윈도우 이벤트(WindowEvent)의 처리
**/
import java.awt.*;
import java.awt.event.*;
class AdapterFrame extends Frame{
    public AdapterFrame(){
        this.addWindowListener(
            new WindowAdapter(){
                public void windowClosing(WindowEvent e){
                    System.exit(0);
                }
            }
        );
    }
}
 
public class AdapterFrameMain{
    public static void main(String[] args){
      Frame f = new AdapterFrame();
      f.setSize(300,100);
      f.setTitle("WindowAdapter 구현");
      f.setVisible(true);
    }
}
/***
c:\javasrc\chap13>javac AdapterFrameMain.java
c:\javasrc\chap13>java AdapterFrameMain
그림1
 
***/
그림1 



WindowListener 는 7개의 추상 메서드를 가지고 있다. WindowListener에 관련된 단 하나의 이벤트를 처리해주려 해도 7개의 메서드를 모두 구현해주어야 한다. 그러나 WindowAdapter를 사용한다면 이미 빈 괄호({ })로 모두 구현되어 있기 때문에 원하는 메서드 하나만 재정의해주면 된다. 

□ Listener & Adapter
◇ Listener : 이벤트를 받아 처리하는 Event Handler
◇ Adapter : 해당 Listener를 상속받아 구현한 클래스

Adapter 클래스를 이용해서 이벤트를 처리하면 필요한 부분의 메서드만 골라서 재정의해서 사용할 수 있기 때문에 코드가 간결해지고 명확해지는 장점이 있다. 다음으로 각각의 Listener와 Event에 관련된 사항들을 알아보자.