一、 适配器模式
1. 概述
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
2. 模式中的角色
Target: 目标接口,客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
Adaptee:需要适配的类或适配者类。
Adapter: 适配器,通过包装一个需要适配的对象,把原接口转换成目标接口。
3. 实现方法
适配器模式分为类适配器模式和对象适配器模式,类适配器通过继承,是静态的定义方式;而对象适配器通过代理,是动态组合的方式。
(1)类适配器 (2)对象适配器
a. Spring中的Controller适配器
// Adapter接口 public interface HandlerAdapter { public boolean supports(Object handler); public void handle(Object handler); } // Adapter实现类,每个Adaptee都有其对应的适配器类 public class HttpHandlerAdapter implements HandlerAdapter { public boolean supports(Object handler) { return (handler instanceof HttpController); } public void handle(Object handler) { ((HttpController)handler).doHttpHandler(); } } public class AnnotationHandlerAdapter implements HandlerAdapter { } // Adaptee接口,Controller中没有通用接口,需要通过适配器转换 public interface Controller { } // Adaptee实现类 public class HttpController implements Controller{ public void doHttpHandler(){ } } public class AnnotationController implements Controller{ } // 目标接口,模拟一个DispatcherServlet public class DispatchServlet { // 采用对象适配器方法 public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>(); public DispatchServlet(){ handlerAdapters.add(new HttpHandlerAdapter()); handlerAdapters.add(new AnnotationHandlerAdapter()); } public void doDispatch(){ HttpController controller = new HttpController(); HandlerAdapter adapter = getHandler(controller); adapter.handle(controller); // 终极目标:通过适配器执行对应的controller对应方法
// 如果没有适配器,需要对controller加以判断 if(controller instanceof HttpController) controller.doHttpHandler();
// 当新增一种controller,就要再加一行代码,这种形式就使得程序难以维护.而使用适配器扩展Controller时,只需要增加一个适配器类,提高代码扩展性 } public HandlerAdapter getHandler(Controller controller){ for(HandlerAdapter adapter: this.handlerAdapters){ if(adapter.supports(controller)){ return adapter; } } return null; } public static void main(String[] args){ new DispatchServlet().doDispatch(); } }
b. Java Swing常见的事件监听适配器,使用该适配器就不需要实现KeyListener中的所有方法,只须实现所需函数。
// Target: KeyListener, Adapter: KeyAdapter, Adaptee: KeyEvent public abstract class KeyAdapter implements KeyListener { public void keyTyped(KeyEvent e) {} public void keyPressed(KeyEvent e) {} public void keyReleased(KeyEvent e) {} }
4.1 适配器模式的优点
更好的复用性:系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
更好的扩展性:在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
4.2 适配器模式的缺点
过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。