设计模式系列8-适配器模式

适配器模式(Adapter Pattern)是指将一个类的接口转换成客户期望的另一个接口,使 原本的接口不兼容的类可以一起工作,属于结构型设计模式

应用场景

  1. 已经存在的类,它的方法和需求不匹配(方法结果相同或相似)的情况。
  2. 适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决方案。有点亡羊补牢的感觉。

生活中也非常的应用场景,例如电源插转换头、手机充电转换头、显示器转接头。

案例

在中国民用电都是 220V 交流电,但我们手机使用的锂电池使用的 5V 直流电。因此,我们给手机充电时就需要使用电源适配器来进行转换

220V交流电

创建 AC220 类,表示 220V 交流电

public class AC220 {

    public int outputAC220V(){
        int output = 220;
        System.out.println("输出电流" + output + "V");
        return output;
    }
}

5V电流

创建 DC5 接口,表示 5V 直流电的标准

public interface DC5 {

    int outoupDC5V();
}

适配器

创建电源适配器 PowerAdapter 类

public class PowerAdapter implements DC5 {

   private AC220 ac220;

    public PowerAdapter(AC220 ac220) {
        this.ac220 = ac220;
    }

    public int outoupDC5V() {
        int adapterInput = ac220.outputAC220V();
        int adapterOutput = adapterInput / 44;
        System.out.println("使用PowerAdapter输入AC:" + adapterInput + "V,输出DC:" + adapterOutput + "V");
        return adapterOutput;
    }
}

测试

public static void main(String[] args) {
        DC5 dc5 = new PowerAdapter(new AC220());
        dc5.outoupDC5V();
    }

通过增加 PowerAdapter 电源适配器,实现了二者的兼容

源码体现

Spring

Spring 中适配器模式也应用得非常广泛,例如:SpringAOP 中的 AdvisorAdapter 类, 它有三个实现类 MethodBeforeAdviceAdapterAfterReturningAdviceAdapterThrowsAdviceAdapter,先来看顶层接口 AdvisorAdapter 的源代码

public interface AdvisorAdapter {
    boolean supportsAdvice(Advice var1);

    MethodInterceptor getInterceptor(Advisor var1);
}
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof MethodBeforeAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
		return new MethodBeforeAdviceInterceptor(advice);
	}

}

Spring 会根据不同的 AOP 配置来确定使用对应的 Advice,跟策略模式不同的一个方法可以同时拥有多个 Advice

SpringMVC

下面再来看一个 SpringMVC 中的 HandlerAdapter 类,它也有多个子类
image

其适配调用的关键代码还是在 DispatcherServletdoDispatch()方法中

# 在 doDispatch()方法中调用了 getHandlerAdapter()方法
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());

# 在 getHandlerAdapter()方法中循环调用了 supports()方法判断是否兼容,循环迭代集 合中的 Adapter 又是在初始化时早已赋值
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        if (this.handlerAdapters != null) {
            Iterator var2 = this.handlerAdapters.iterator();

            while(var2.hasNext()) {
                HandlerAdapter adapter = (HandlerAdapter)var2.next();
                if (adapter.supports(handler)) {
                    return adapter;
                }
            }
        }

        throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }

适配器模式的优缺点

  • 优点:
  1. 能提高类的透明性和复用,现有的类复用但不需要改变。
  2. 目标类和适配器类解耦,提高程序的扩展性。
  3. 在很多业务场景中符合开闭原则。
  • 缺点:
  1. 适配器编写过程需要全面考虑,可能会增加系统的复杂性。
  2. 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
posted @ 2021-09-27 20:07  狻猊的主人  阅读(96)  评论(0)    收藏  举报