继续创作,加速成长!这是我参加「日新方案 10 月更文挑战」的第16天,点击检查活动详情

前言

适配器形式应用十分广泛,咱们日子中很多事物都运用了适配器形式,比如日子中常见的手机充电的场景,咱们都知道家庭中插座电压是220V,但是咱们手机数据线上标注的却是5V-3A、10V-4A,那么手机是如何从220V的电压中充电的呢?关键就是那个充电头充当了适配器的形式,将电压转换为手机能承受的小电压,适配器形式也是这样的原理。

一文了解适配器模式

适配器形式作业原理

  • 将一个类的接口转换成另一种接口,让本来接口不兼容的类能够兼容
  • 从用户的视点看不到被适配者,是解耦的
  • 用户调用适配器转化出来的方针接口办法,适配器再调用被适配者的相关接口办法
  • 用户收到反应成果,感觉仅仅和方针接口交互。

适配器形式完结

适配器形式有三种比较常见的完结方式:

  • 类适配器形式
  • 目标适配器形式
  • 接口适配器形式

类适配器形式

简单来说就是Adapter类经过承继src类,完结dst接口完结src到dst的适配。

一文了解适配器模式
src类界说源220V输出电压

public class Voltage220V {
    public int OutPut220(){
        int src = 220;
        System.out.println("输出电压220");
        return src;
    }
}

dst界说接口输入5v电压

interface Voltage5V {
    public int OutPut5();
}

Adapter承继src,完结dst

public class VoltageAdapter extends Voltage220V implements Voltage5V{
    @Override
    public int OutPut5() {
        int src = OutPut220();
        int dst = src/44;
        System.out.println("适配器转为5V");
        return dst;
    }
}

手机调用dst接口输入5v办法进行充电,实际上调用的是Adaoter类中完结dst的output5()办法。

public class Phone {
    public void Charge(Voltage5V voltage5V){
        int dst = voltage5V.OutPut5();
        System.out.println("5V充电");
    }
}

总结:

  1. Java是单承继机制,反以类适配器需求承继src类这一点算是一个缺陷,因为这要求dst有必要是接口,有一定局限性;
  2. src类的办法在Adapter中都会暴露出来,也增加了运用的本钱。
  3. 因为其承继了src类,所以它能够依据需求重写src类的办法,使得Adapter的灵活性增强了。

目标适配器形式

基本思路和类的适配器形式相同,仅仅将Adapter类作修正,不是承继src类,而是持有src类的实例,切处理兼容性的问题。即:持有src类,完结 dst 类接口,完结src->dst的适配。

一文了解适配器模式

在Adapter类中,不再承继src,而是创立Voltage220V实例目标

public class VoltageAdapter implements Voltage5V {
    private Voltage220V voltage220V;
    public VoltageAdapter(Voltage220V voltage220V) {
        this.voltage220V = voltage220V;
    }
    @Override
    public int OutPut5() {
        int src = voltage220V.OutPut220();
        int dst = src/44;
        System.out.println("适配器转为5V");
        return dst;
    }
}

目标适配器和类适配琴其实算是同一种思想,只不过完结方式不同。 依据合成复用准则,运用组合代替承继,所以它处理了类适配器有必要承继src的局限性问题,也不再要求dst有必要是接口。运用本钱更低,更灵活。

接口适配器形式

当不需求全部完结接口供给的办法时,可先设计一个抽象类完结接口,并为该接中每个办法供给一个默许完结(空办法),那么该抽象类的子类可有挑选地掩盖父类的某些办法来完结需求。

一文了解适配器模式
接口界说办法

public interface test {
    public void m1();
    public void m2();
    public void m3();
    public void m4();
}

抽象类为接口中的办法供给空完结

public abstract class testAdapter implements test{
    public void m1(){}
    public void m2(){}
    public void m3(){}
    public void m4(){}
}

运用时针对需求的办法进行完结

public class Client {
    public static void main(String[] args) {
        testAdapter adapter = new testAdapter(){
            public void m1(){
                System.out.println("完结m1办法");
            }
        };
        adapter.m1();
    }
}

接口适配器形式适用于不需求src一切办法的场景。

手写SpringMVC中的适配器

首先回顾一下SpringMVC的作业原理:

  1. 用户发送恳求至前端控制器DispatcherServlet。
  2. DispatcherServlet收到恳求调用HandlerMapping处理器映射器。
  3. 处理器映射器找到详细的处理器(能够依据xml装备、注解进行查找),生成处理器目标及处理器拦截器(如果有则生成)一并回来给DispatcherServlet.
  4. DispatcherServlet调用HandlerAdapter处理器适配器。
  5. HandlerAdapter经过适配调用详细的处理器(Controller,也叫后端控制器)。
  6. Controller履行完结回来ModelAndView。
  7. HandlerAdapter将controller履行成果ModelAndView回来给DispatcherServlet
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
  9. ViewReslover解析后回来详细View。
  10. DispatcherServlet依据View进行渲染视图(即将模型数据填充至视图中)。DispatcherServlet呼应用户。

要想手写适配器处理流程,首先需求了解类图

一文了解适配器模式
恳求抵达DispatchServlet,DispatchServlet需求依据恳求挑选对应的处理器适配器也就是HandlerAdapter,处理器适配器调用对应的处理器Controller。

界说Controller接口,多种Controller完结Controller接口,完结自己的办法。


//多种Controller完结  
public interface Controller {
}
class HttpController implements Controller {
   public void doHttpHandler() {
      System.out.println("http...");
   }
}
class SimpleController implements Controller {
   public void doSimplerHandler() {
      System.out.println("simple...");
   }
}
class AnnotationController implements Controller {
   public void doAnnotationHandler() {
      System.out.println("annotation...");
   }
}

界说HandleAdapter,依据Controller完结对应的适配器

///界说一个Adapter接口 
public interface HandlerAdapter {
   public boolean supports(Object handler);
   public void handle(Object handler);
}
// 多种适配器类
class SimpleHandlerAdapter implements HandlerAdapter {
   public void handle(Object handler) {
      ((SimpleController) handler).doSimplerHandler();
   }
   public boolean supports(Object handler) {
      return (handler instanceof SimpleController);
   }
}
class HttpHandlerAdapter implements HandlerAdapter {
   public void handle(Object handler) {
      ((HttpController) handler).doHttpHandler();
   }
   public boolean supports(Object handler) {
      return (handler instanceof HttpController);
   }
}
class AnnotationHandlerAdapter implements HandlerAdapter {
   public void handle(Object handler) {
      ((AnnotationController) handler).doAnnotationHandler();
   }
   public boolean supports(Object handler) {
      return (handler instanceof AnnotationController);
   }
}

DispatchServlet进行分发

public class DispatchServlet {
   //适配器列表
   public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();
   //将适配器添加到列表
   public DispatchServlet() {
      handlerAdapters.add(new AnnotationHandlerAdapter());
      handlerAdapters.add(new HttpHandlerAdapter());
      handlerAdapters.add(new SimpleHandlerAdapter());
   }
   //适配器分配
   public void doDispatch() {
      // 此处模拟SpringMVC从request取handler的目标,
      // 适配器能够获取到希望的Controller
       HttpController controller = new HttpController();
      // AnnotationController controller = new AnnotationController();
      //SimpleController controller = new SimpleController();
      // 得到对应适配器
      HandlerAdapter adapter = getHandler(controller);
      // 经过适配器履行对应的controller对应办法
      adapter.handle(controller);
   }
   public HandlerAdapter getHandler(Controller controller) {
      //遍历:依据得到的controller(handler), 回来对应适配器
      for (HandlerAdapter adapter : this.handlerAdapters) {
         if (adapter.supports(controller)) {
            return adapter;
         }
      }
      return null;
   }
   public static void main(String[] args) {
      new DispatchServlet().doDispatch(); // http...
   }
}