Java设计模式——适配器模式

Java设计模式——适配器模式

1 类适配器模式

1.1 类适配器模式介绍

Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。

Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。

Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。

基本介绍:Adapter类,通过继承Adaptee类,实现target接口,完成Adaptee到target的适配

Adaptee类

public class AC220V {

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

target类

public interface DC5 {
    int output5V();
}

Adapter

public class ChinaPowerAdapter extends AC220V implements DC5 {
    @Override
    public int output5V() {
        int output220 = output220V();
        System.out.println("接入220V电压,输出5V电压");
        return output220/44;
    }
}

通过适配器将220V电压输出转换为需要的5V输出

2 对象适配器模式

2.1 对象适配器模式介绍

基本思路与类适配器模式相同,只是将Adapter类修改,不是继承Adaptee类,而是持有Adaptee的实例

根据“合成复用原则”,在系统中尽量使用关联关系来替代继承关系

对象适配器模式是适配器模式中常用的一种

Adaptee

public class AC220V {

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

target类

public interface DC5 {
    int output5V();
}

Adapter

public class ChinaPowerAdapter implements DC5 {

   private AC220V ac220V;


    public ChinaPowerAdapter(AC220V ac220V) {
        this.ac220V = ac220V;
    }
   
    @Override
    public int output5V() {
        int output = 0;
        if (ac220V != null) {
            output = ac220V.output220V() / 44;
        }
        return output;
    }
}
2.2 优点

解决了类适配器必须继承Adaptee的局限性问题,也不再要求target必须是接口

3 接口适配器模式

3.1 接口适配器模式介绍

当不需要全部实现接口提供的方法时,可先设计一个抽象实现接口,并为接口中的每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择第覆盖父类中的某些方法来实现需求

适用于一个接口不想使用其所有的方法的情况

AC接口

public interface AC {
    int output();
}

AC接口实现类

public class AC220V implements AC{
    @Override
    public int output() {
        int output = 220;
        System.out.println("输出220V电压");
        return output;
    }
}

多输出多功能接口

public interface DCOutput {

    int output5V();

    int output10V();

    int output15V();

    int output20V();
}

默认实现接口抽象类

public abstract class PowerAdapter implements DCOutput {

    protected AC ac;

    public PowerAdapter(AC ac) {
        this.ac = ac;
    }

    @Override
    public int output5V() {
        return 0;
    }

    @Override
    public int output10V() {
        return 0;
    }

    @Override
    public int output15V() {
        return 0;
    }

    @Override
    public int output20V() {
        return 0;
    }
}

只关注输出为5V的功能,故重写抽象类的5V方法

public class Test {
    public static void main(String[] args) {
        PowerAdapter powerAdapter = new PowerAdapter(new AC220V()) {
            @Override
            public int output5V() {
                int output = 0;
                if (ac != null) {
                    output = ac.output() / 44;
                }
                System.out.println("输出5V");
                return output;
            }
        };

        powerAdapter.output5V();
    }
}

4 源码分析

4.1 SpringMVC执行流程
  • 用户发送出请求到前端控制器DispatcherServlet。
  • DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
  • HandlerMapping找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
  • DispatcherServlet调用HandlerAdapter(处理器适配器)。
  • HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。
  • Controller执行完成返回ModelAndView对象。
  • HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
  • DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。
  • ViewReslover解析后返回具体View(视图)。
  • DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  • DispatcherServlet响应用户。

4.2 SpringMVC中的适配器模式

在SpringMVC中默认会存在三种Adapter:HttpRequestHandlerAdapter,SimpleControllerHandlerAdapter和AnnotationMethodHandlerAdapter

,他们会根据Controller的类型来分配任务。

  • AnnotationMethodHandlerAdapter主要是适配注解类处理器,注解类处理器就是我们经常使用的@Controller的这类处理器
  • HttpRequestHandlerAdapter主要是适配静态资源处理器,静态资源处理器就是实现了HttpRequestHandler接口的处理器,这类处理器的作用是处理通过SpringMVC来访问的静态资源的请求。
  • SimpleControllerHandlerAdapter是Controller处理适配器,适配实现了Controller接口或Controller接口子类的处理器,比如我们写Controller来继承MultiActionController.

利用不同的适配器处理不同类型的Controller请求,并将返回的数据封装成ModelAndView返回,完成返回数据的统一。并且使用适配器模式后,以后如果增加其他类型的Controller,只需增加相应的Adapter即可,保证了开闭原则—对扩展开放,对修改关闭

HandlerAdapter接口

public interface HandlerAdapter {
    boolean supports(Object var1);

    ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;

    long getLastModified(HttpServletRequest var1, Object var2);
}

HandlerAdapter接口一个实现

public class HttpRequestHandlerAdapter implements HandlerAdapter {
    public HttpRequestHandlerAdapter() {
    }

    public boolean supports(Object handler) {
        return handler instanceof HttpRequestHandler;
    }

    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        ((HttpRequestHandler)handler).handleRequest(request, response);
        return null;
    }

    public long getLastModified(HttpServletRequest request, Object handler) {
        return handler instanceof LastModified ? ((LastModified)handler).getLastModified(request) : -1L;
    }
}

Spring容器启动后会将配置的HandlerAdapter存放到一个List对象中,当对应的请求来时,在DispatcherServlet的doDispatch方法中找到合适的HandlerAdapter(找到一个就返回),并通过相应的HandlerAdapter完成相应的请求,返回相应ModelAndView

public class DispatcherServlet extends FrameworkServlet {
    private List<HandlerAdapter> handlerAdapters;
    
    //初始化handlerAdapters
    //根据配置注册handlerAdapters
    private void initHandlerAdapters(ApplicationContext context) {
        //..省略...
    }
    
    // 遍历所有的 HandlerAdapters,通过 supports 判断找到匹配的适配器
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        Iterator var2 = this.handlerAdapters.iterator();

        HandlerAdapter ha;
        do {
            if (!var2.hasNext()) {
                throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
            }

            ha = (HandlerAdapter)var2.next();
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Testing handler adapter [" + ha + "]");
            }
        } while(!ha.supports(handler));

        return ha;
    }
	
	// 分发请求,请求需要找到匹配的适配器来处理
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
         ModelAndView mv = null;

		// Determine handler for the current request.
		mappedHandler = getHandler(processedRequest);
			
		// 确定当前请求的匹配的适配器.
		HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

		ha.getLastModified(request, mappedHandler.getHandler());
					
		mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    }
	// ...省略...
}	

5 仿照例子

AC接口

public interface AC {
    int outputAC();
}

AC110实现类

public class AC110 implements AC {
    @Override
    public int outputAC() {
        return 110;
    }
}

AC220实现类

public class AC220 implements AC {

    @Override
    public int outputAC() {
        return 220;
    }
}

Adapter接口

public interface DC5Adapter {
    int outputDC5V(AC output);

    boolean support(AC output);
}

Adapter实现类

public class ChinaPowerAdapter implements DC5Adapter {
    @Override
    public int outputDC5V(AC output) {
        int chinaOutput = output.outputAC();
        System.out.println("使用ChinaPowerAdapter变压适配器");
        return chinaOutput/44;
    }

    @Override
    public boolean support(AC output) {
        return 220==output.outputAC();
    }
}

Adapter实现类

public class JapanPowerAdapter implements DC5Adapter {
    @Override
    public int outputDC5V(AC output) {
        int japanOutput = output.outputAC();
        System.out.println("使用JapanPowerAdapter变压适配器");
        return japanOutput/22;
    }

    @Override
    public boolean support(AC output) {
        return 110==output.outputAC();
    }
}

测试

public class Test {

    private List<DC5Adapter> adapters = new ArrayList<>();

    //注册Adapter
    public Test() {
        adapters.add(new ChinaPowerAdapter());
        adapters.add(new JapanPowerAdapter());
    }

    //根据support方法找到合适的Adapter
    public DC5Adapter getFitAdapter(AC ac) {
        DC5Adapter dc5Adapter = null;

        for (DC5Adapter temp : adapters) {
            if (temp.support(ac)) {
                dc5Adapter = temp;
                break;
            }
        }

        return dc5Adapter;
    }

    public static void main(String[] args) {
        Test test = new Test();
        AC china = new AC220();
        AC japan = new AC110();

        DC5Adapter fitAdapter = test.getFitAdapter(china);
        fitAdapter.outputDC5V(china);

        DC5Adapter fitAdapter1 = test.getFitAdapter(japan);
        fitAdapter1.outputDC5V(japan);
    }
}

参考:设计模式 | 适配器模式及典型应用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值