Java描述设计模式(07):适配器模式
本文源码:GitHub·点这里 || GitEE·点这里 一、适配器模式简介 1、基础概念 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。适配器模式有类适配器模式和对象适配器模式,以及缺省(接口)适配器,三种不同的形式。 2、生活场景 基于适配器模式,把220V的电压,转换为需要的110V电压。 public class C01_InScene { public static void main(String[] args) { CurrentAdapter adapter = new CurrentAdapter() ; System.out.println(adapter.get110VCurrent()) ; } } // 220V电流 class Current220V { public int get220VCurrent (){ return 220 ; } } // 110V电流接口 interface Current110V { int get110VCurrent () ; } // 电流适配器 class CurrentAdapter extends Current220V implements Current110V { // 电流转换方法 @Override public int get110VCurrent() { int high = get220VCurrent() ; int low = high/2 ; return low ; } } 二、类适配器 1、模式简介 类的适配器模式把适配的类的API转换成为目标类的API。 2、核心角色 目标(Target)角色 这就是所期待得到的接口。 源(Adapee)角色: 现在需要适配的接口。 适配器(Adaper)角色 适配器类是本模式的核心。适配器把源接口转换成目标接口。 3、源码实现 interface Target { void sampleOperation1(); void sampleOperation2(); } class Adaptee { public void sampleOperation1(){ System.out.println("Adaptee.sampleOperation1()"); } } class Adapter extends Adaptee implements Target{ @Override public void sampleOperation2() { System.out.println("Adapter.sampleOperation2()"); } } 三、对象适配器 1、模式简介 与类的适配器模式一样,对象的适配器模式把被适配的类的API转换成为目标类的API,与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。 2、源码实现 interface Target1 { void sampleOperation1(); void sampleOperation2(); } class Adaptee1 { public void sampleOperation1(){ System.out.println("Adaptee.sampleOperation1()"); } } class Adapter1 implements Target1 { private Adaptee1 adaptee ; public Adapter1 (Adaptee1 adaptee){ this.adaptee = adaptee; } public void sampleOperation1() { this.adaptee.sampleOperation1(); } @Override public void sampleOperation2() { System.out.println("Adapter.sampleOperation2()"); } } 四、接口适配器 1、模式简介 缺省(接口)适配(Default Adapter)模式为一个接口提供缺省实现,这样子类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。 2、源代码实现 public class C04_AdapterInte { public static void main(String[] args) { ServiceAdapter adapter = new ServiceAdapter(){ @Override public int serviceOperation2() { return 22 ; } }; System.out.println(adapter.serviceOperation2()); } } interface AbstractService { void serviceOperation1(); int serviceOperation2(); String serviceOperation3(); } class ServiceAdapter implements AbstractService{ @Override public void serviceOperation1() { } @Override public int serviceOperation2() { return 0; } @Override public String serviceOperation3() { return null; } } 五、Spring框架应用 1、应用场景描述 在SpringMvc执行控制执行请求的时候,有这样一个流程 1)前段控制器DispatcherServlet调用处理器适配器去执行Handler(也就是Controller);2)处理器适配器去执行Handler,给适配器返回ModelAndView ;3)处理器适配器向前端控制器返回ModelAndView ; 2、流程分析 核心接口和实现 Controller和HandlerAdapter两核心接口。 HandlerAdapter 适配器接口,使Handler有对应的适配器实现类,适配器代替Handler(控制层Controller)执行相应的方法。 public interface HandlerAdapter { // 判断类型是否匹配 boolean supports(Object var1); // 执行方法,返回ModelAndView ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception; } supports()方法传入处理器,判断适配器是否支持,如果支持则返回支持的适配器实现类。 DispatchServlert 抽取源码中体现流程的几个步骤。 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerExecutionChain mappedHandler = null; mappedHandler = this.getHandler(processedRequest); HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); mappedHandler.applyPostHandle(processedRequest, response, mv); } SimpleControllerHandlerAdapter 最后看下supports和handle两个方法的具体实现。 public class SimpleControllerHandlerAdapter implements HandlerAdapter { public SimpleControllerHandlerAdapter() { } public boolean supports(Object handler) { return handler instanceof Controller; } public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller)handler).handleRequest(request, response); } } 六、适配器优缺点 1、优点分析 更好的复用性,系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。更好的扩展性。 2、缺点分析 过多的使用适配器,会让系统非常零乱,不易整体进行把控。 七、源代码地址 GitHub·地址 https://github.com/cicadasmile/model-arithmetic-parent GitEE·地址 https://gitee.com/cicadasmile/model-arithmetic-parent