Event Handler - 13.4.2 Listener와 Adapter
출처 : 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를 구현해서 프레임의 종료를 구현하는 예이다.
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 ***/ |

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의 완성된 예이다.
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 ***/ |

WindowListener 는 7개의 추상 메서드를 가지고 있다. WindowListener에 관련된 단 하나의 이벤트를 처리해주려 해도 7개의 메서드를 모두 구현해주어야 한다. 그러나 WindowAdapter를 사용한다면 이미 빈 괄호({ })로 모두 구현되어 있기 때문에 원하는 메서드 하나만 재정의해주면 된다.
□ Listener & Adapter
◇ Listener : 이벤트를 받아 처리하는 Event Handler
◇ Adapter : 해당 Listener를 상속받아 구현한 클래스
Adapter 클래스를 이용해서 이벤트를 처리하면 필요한 부분의 메서드만 골라서 재정의해서 사용할 수 있기 때문에 코드가 간결해지고 명확해지는 장점이 있다. 다음으로 각각의 Listener와 Event에 관련된 사항들을 알아보자.