JAVA设计模式之适配器模式(adapter)
适配器模式使用案例:
- 数据库连接中的驱动
- java虚拟机
- zookeeper客户端
- redis客户端
误区:
- java中各种带Adapter后缀的类并不是使用适配器模式只是方便程序员编程使用。经典的应用场景如下:
1 package com.srr.dp.adapter; 2 3 import java.awt.*;; 4 import java.awt.event.*; 5 6 public class T extends Frame{ 7 8 public static void main(String[] args) { 9 T t = new T(); 10 t.addKeyListener(new KeyAdapter(){ 11 public void keyPressed(KeyEvent e) { 12 } 13 }); 14 t.addWindowListener(new WindowAdapter() { 15 @Override 16 public void windowOpened(WindowEvent e) { 17 super.windowOpened(e); 18 } 19 }); 20 } 21 }
其实我们可以直接使用KeyListener和WindowListener,代码如下:
1 package com.srr.dp.adapter; 2 3 import java.awt.*;; 4 import java.awt.event.*; 5 6 public class T2 extends Frame{ 7 8 public static void main(String[] args) { 9 T2 t = new T2(); 10 t.addKeyListener(new KeyListener(){ 11 @Override 12 public void keyTyped(KeyEvent e) { 13 14 } 15 public void keyPressed(KeyEvent e) { 16 } 17 @Override 18 public void keyReleased(KeyEvent e) { 19 20 } 21 }); 22 23 t.addWindowListener(new WindowListener() { 24 25 @Override 26 public void windowOpened(WindowEvent e) { 27 28 } 29 30 @Override 31 public void windowClosing(WindowEvent e) { 32 33 } 34 35 @Override 36 public void windowClosed(WindowEvent e) { 37 38 } 39 40 @Override 41 public void windowIconified(WindowEvent e) { 42 43 } 44 45 @Override 46 public void windowDeiconified(WindowEvent e) { 47 48 } 49 50 @Override 51 public void windowActivated(WindowEvent e) { 52 53 } 54 55 @Override 56 public void windowDeactivated(WindowEvent e) { 57 58 } 59 }); 60 } 61 }
对比发现,使用KeyListener和WindowListener我们需要实现多个方法,想反使用KeyAdapter和WindowAdapter更方便只需实现较少的方法即可,查看源码发现并其实没有使用适配器模式而是
/* * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package java.awt.event; /** * An abstract adapter class for receiving window events. * The methods in this class are empty. This class exists as * convenience for creating listener objects. * <P> * Extend this class to create a <code>WindowEvent</code> listener * and override the methods for the events of interest. (If you implement the * <code>WindowListener</code> interface, you have to define all of * the methods in it. This abstract class defines null methods for them * all, so you can only have to define methods for events you care about.) * <P> * Create a listener object using the extended class and then register it with * a Window using the window's <code>addWindowListener</code> * method. When the window's status changes by virtue of being opened, * closed, activated or deactivated, iconified or deiconified, * the relevant method in the listener * object is invoked, and the <code>WindowEvent</code> is passed to it. * * @see WindowEvent * @see WindowListener * @see <a href="https://docs.oracle.com/javase/tutorial/uiswing/events/windowlistener.html">Tutorial: Writing a Window Listener</a> * * @author Carl Quinn * @author Amy Fowler * @author David Mendenhall * @since 1.1 */ public abstract class WindowAdapter implements WindowListener, WindowStateListener, WindowFocusListener { /** * Invoked when a window has been opened. */ public void windowOpened(WindowEvent e) {} /** * Invoked when a window is in the process of being closed. * The close operation can be overridden at this point. */ public void windowClosing(WindowEvent e) {} /** * Invoked when a window has been closed. */ public void windowClosed(WindowEvent e) {} /** * Invoked when a window is iconified. */ public void windowIconified(WindowEvent e) {} /** * Invoked when a window is de-iconified. */ public void windowDeiconified(WindowEvent e) {} /** * Invoked when a window is activated. */ public void windowActivated(WindowEvent e) {} /** * Invoked when a window is de-activated. */ public void windowDeactivated(WindowEvent e) {} /** * Invoked when a window state is changed. * @since 1.4 */ public void windowStateChanged(WindowEvent e) {} /** * Invoked when the Window is set to be the focused Window, which means * that the Window, or one of its subcomponents, will receive keyboard * events. * * @since 1.4 */ public void windowGainedFocus(WindowEvent e) {} /** * Invoked when the Window is no longer the focused Window, which means * that keyboard events will no longer be delivered to the Window or any of * its subcomponents. * * @since 1.4 */ public void windowLostFocus(WindowEvent e) {} }
1 /* 2 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. 3 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 * 23 * 24 */ 25 26 package java.awt.event; 27 28 /** 29 * An abstract adapter class for receiving keyboard events. 30 * The methods in this class are empty. This class exists as 31 * convenience for creating listener objects. 32 * <P> 33 * Extend this class to create a <code>KeyEvent</code> listener 34 * and override the methods for the events of interest. (If you implement the 35 * <code>KeyListener</code> interface, you have to define all of 36 * the methods in it. This abstract class defines null methods for them 37 * all, so you can only have to define methods for events you care about.) 38 * <P> 39 * Create a listener object using the extended class and then register it with 40 * a component using the component's <code>addKeyListener</code> 41 * method. When a key is pressed, released, or typed, 42 * the relevant method in the listener object is invoked, 43 * and the <code>KeyEvent</code> is passed to it. 44 * 45 * @author Carl Quinn 46 * 47 * @see KeyEvent 48 * @see KeyListener 49 * @see <a href="https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html">Tutorial: Writing a Key Listener</a> 50 * 51 * @since 1.1 52 */ 53 public abstract class KeyAdapter implements KeyListener { 54 /** 55 * Invoked when a key has been typed. 56 * This event occurs when a key press is followed by a key release. 57 */ 58 public void keyTyped(KeyEvent e) {} 59 60 /** 61 * Invoked when a key has been pressed. 62 */ 63 public void keyPressed(KeyEvent e) {} 64 65 /** 66 * Invoked when a key has been released. 67 */ 68 public void keyReleased(KeyEvent e) {} 69 }
KeyAdapter和WindowAdapter帮我们实现了KeyListener和WindowListener接口
接下来,java中经典的使用适配器模式的代码如下,其实我们经常用,请看下面代码:
package com.mashibing.dp.adapter; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; /** * 适配器模式使用案例 */ public class Main { public static void main(String[] args) throws Exception { FileInputStream fis = new FileInputStream("D:/test.text"); /** * InputStreamReader就扮演了适配器的角色,因为BufferedReader无法直接使用InputStream */ InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String line = br.readLine(); while (line != null && !line.equals("")) { System.out.println(line); } br.close(); } }