当前位置:   article > 正文

【源码分析设计模式 10】SpringMVC中的适配器模式

【源码分析设计模式 10】SpringMVC中的适配器模式

一、基本介绍

适配器这个词我们应该很熟悉,天天都在使用,手机充电时,电源线头头就叫电源适配器,干什么用的呢?把220V电压转换成手机充电时使用的电压,那么适配器是不是很好理解了,下面看一下定义。

Adapter适配器模式,将一个类的接口转换成客户希望的另外一个接口。使原本由于接口不兼容而不能一起工作的那些类可以一起工作了。

适配器模式有“类适配器”和“对象适配器”两种不同的形式。

二、适配器模式的结构

1、目标(Target)

定义一个客户端使用的特定接口。

2、客户端(Client)

使用目标接口,与和目标接口一致的对象合作。

3、被适配者(Adaptee)

一个现存需要适配的接口。

4、适配器(Adapter)

负责将Adaptee的接口转换为Target的接口。适配器是一个具体的类,这是该模式的核心。

三、适配器模式的优缺点

1、优点

  • 可以让任何两个没有关联的类一起运行;
  • 增加了类的透明性;
  • 提高了类的复用度;
  • 灵活性非常好;

2、缺点

  • 过多使用适配器会使系统非常凌乱;
  • 由于java是单继承的,所以只能适配一个适配器类,而且目标类必须是抽象的;
  • 只有碰到无法改变原有设计和代码的情况下,才会考虑适配器模式;

四、适配器模式的使用场景

1、系统需要使用现有的类,从而类的接口不符合系统的需要。

2、想建立一个可以重复使用的类,用于一些彼此之间没有太大关联的一些类。

3、通过接口转换,将一个类插入另一个类中。

五、类适配器

通过继承进行适配(类间继承)。URL结构图如下:

1、Target

Target目标角色,该角色定义把其它类转换成期望接口,通常情况下是一个接口或一个抽象类,一般不会是实现类。

  1. public interface Target {
  2. public void request();
  3. }

2、Adaptee

Adaptee源角色,想把谁转换为目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象。

  1. public class Adaptee {
  2. public void specificRequest() {
  3. System.out.println("特殊请求");
  4. }
  5. }

3、Adapter

Adapter适配器角色,是适配器模式的核心角色,它的职责是通过继承或类关联的方式把源角色转换成目标角色。

  1. public class Adapter extends Adaptee implements Target {
  2. @Override
  3. public void request() {
  4. super.specificRequest();
  5. }
  6. }

4、ConcreteTarget

  1. package designMode.adapter.sxn;
  2. public class ConcreteTarget implements Target {
  3. @Override
  4. public void request() {
  5. System.out.println("普通请求");
  6. }
  7. }

5、测试类

  1. package designMode.adapter.sxn;
  2. public class Client {
  3. public static void main(String[] args) {
  4. //原有业务逻辑
  5. Target target = new ConcreteTarget();
  6. target.request();
  7. //增加适配器后的业务逻辑
  8. Target target2 = new Adapter();
  9. target2.request();
  10. }
  11. }

6、控制台输出

六、对象适配器

 通过对象层次的关联关系进行委托(对象的合成关系/关联关系)。UML结构图如下:

1、Target

客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。

  1. package designMode.adapter.sxn;
  2. public class Target {
  3. public void request() {
  4. System.out.println("普通请求");
  5. }
  6. }

2、Adaptee

需要适配的类。

  1. package designMode.adapter.sxn;
  2. public class Adaptee {
  3. public void specificRequest() {
  4. System.out.println("特殊请求");
  5. }
  6. }

3、Adapter

通过在内部包装一个Adaptee对象,把源接口转换成目标接口。

  1. package designMode.adapter.sxn;
  2. public class Adapter extends Target{
  3. private Adaptee adaptee = new Adaptee();
  4. @Override
  5. public void request() {
  6. adaptee.specificRequest();
  7. }
  8. }

4、测试类

  1. package designMode.adapter.sxn;
  2. public class Client {
  3. public static void main(String[] args) {
  4. Target target = new Adapter();
  5. target.request();
  6. }
  7. }

5、控制台输出

七、适配器模式在SpringMVC框架应用的源码剖析

1、SpringMVC中的HandlerAdapter使用了适配器模式;

2、使用HandlerAdapter的原因分析

可以看到处理器的类型不同,有多重实现方式,那么调用方式就不是确定的,如果需要直接调用controller方法,需要调用的时候就得不断使用ifelse来进行判断是哪一种子类然后执行。那么如果后面要扩展controller,就得修改原来的代码,违背了开闭原则。

3、SpringMVC通过适配器模式获取对应的controller步骤

  • Spring定义了一个适配接口,使得每一种controller有一种对应的适配器实现类;
  • 适配器代替controller执行相应的方法
  • 扩展controller时,只需要增加一个适配器类就完成了SpringMVC的扩展;

4、模拟代码实现

  •  controller接口
  1. package com.guor.adapter;
  2. public interface Controller {
  3. }
  4. class HttpController implements Controller {
  5. public void doHttpHandler() {
  6. System.out.println("http...");
  7. }
  8. }
  9. class SimpleController implements Controller {
  10. public void doSimplerHandler() {
  11. System.out.println("simple...");
  12. }
  13. }
  14. class AnnotationController implements Controller {
  15. public void doAnnotationHandler() {
  16. System.out.println("annotation...");
  17. }
  18. }
  • HandlerAdapter接口
  1. package com.guor.adapter;
  2. public interface HandlerAdapter {
  3. public boolean supports(Object handler);
  4. public void handle(Object handler);
  5. }
  6. // 多种适配器类
  7. class SimpleHandlerAdapter implements HandlerAdapter {
  8. public void handle(Object handler) {
  9. ((SimpleController) handler).doSimplerHandler();
  10. }
  11. public boolean supports(Object handler) {
  12. return (handler instanceof SimpleController);
  13. }
  14. }
  15. class HttpHandlerAdapter implements HandlerAdapter {
  16. public void handle(Object handler) {
  17. ((HttpController) handler).doHttpHandler();
  18. }
  19. public boolean supports(Object handler) {
  20. return (handler instanceof HttpController);
  21. }
  22. }
  23. class AnnotationHandlerAdapter implements HandlerAdapter {
  24. public void handle(Object handler) {
  25. ((AnnotationController) handler).doAnnotationHandler();
  26. }
  27. public boolean supports(Object handler) {
  28. return (handler instanceof AnnotationController);
  29. }
  30. }
  • DispatchServlet类
  1. package com.guor.adapter;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class DispatchServlet {
  5. public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();
  6. public DispatchServlet() {
  7. handlerAdapters.add(new AnnotationHandlerAdapter());
  8. handlerAdapters.add(new HttpHandlerAdapter());
  9. handlerAdapters.add(new SimpleHandlerAdapter());
  10. }
  11. public void doDispatch() {
  12. // 此处模拟SpringMVC从request取handler的对象,
  13. // 适配器可以获取到希望的Controller
  14. HttpController controller = new HttpController();
  15. // AnnotationController controller = new AnnotationController();
  16. //SimpleController controller = new SimpleController();
  17. // 得到对应适配器
  18. HandlerAdapter adapter = getHandler(controller);
  19. // 通过适配器执行对应的controller对应方法
  20. adapter.handle(controller);
  21. }
  22. public HandlerAdapter getHandler(Controller controller) {
  23. //遍历:根据得到的controller(handler), 返回对应适配器
  24. for (HandlerAdapter adapter : this.handlerAdapters) {
  25. if (adapter.supports(controller)) {
  26. return adapter;
  27. }
  28. }
  29. return null;
  30. }
  31. public static void main(String[] args) {
  32. new DispatchServlet().doDispatch(); // http...
  33. }
  34. }
  • 控制台输出

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/63424
推荐阅读
相关标签
  

闽ICP备14008679号