ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

适配器模式(实例+框架源码分析)

2021-10-17 19:34:39  阅读:198  来源: 互联网

标签:实例 adapter 5V public 源码 void println 适配器


文章目录

介绍

适配器模式是两个不兼容接口间的桥梁,属于结构型模式。适配器模式分为三类,类适配器模式,对象适配器模式,接口适配器模式。我们生活中有很多适配器模式的例子,例如我们给手机充电,家庭电压是220V直流,手机的电压是5V交流,但是我们依然可以直接给手机充电,就是因为充电器充当了适配器的角色。

1.类适配器模式

演示

例子:把220V直流适配成5V交流。
类图:
在这里插入图片描述

Voltage220V类

package com.jc.adapter.classadapter;

/**
 * @program: 设计模式
 * @description:被适配者
 * @author: Mr.Wang
 * @create: 2021-06-16 20:03
 **/
public class Voltage220V {

    public int output220V() {

        int src = 220;

        return src;
    }
}

Voltage5V接口

package com.jc.adapter.classadapter;

/**
 * 目标接口
 */
public interface Voltage5V {
    int output5V();
}

VoltageApdapter类

package com.jc.adapter.classadapter;/**
* @program: 设计模式
*
* @description: 适配器
*
* @author: Mr.Wang
*
* @create: 2021-06-16 20:05
**/
public class VoltageAdapter extends Voltage220V implements Voltage5V {
    @Override
    public int output5V() {
        int src = output220V();

        src = src / 44;
        System.out.println("220V已经适配成5V啦!可以充电啦!");
        return src;
    }
}

Phone类

package com.jc.adapter.classadapter;/**
* @program: 设计模式
*
* @description: 
*
* @author: Mr.Wang
*
* @create: 2021-06-16 20:06
**/
public class Phone {
    //充电
    public void charging(Voltage5V voltage5V){

        if (voltage5V.output5V() == 5){
            System.out.println("电压为5V~可以充电");
        }else if(voltage5V.output5V() > 5){
            System.out.println("电压大于5V~不可以充电!");
        }
    }
}

Client

package com.jc.adapter.classadapter;/**
* @program: 设计模式
*
* @description: 
*
* @author: Mr.Wang
*
* @create: 2021-06-16 20:08
**/
public class Client {
    public static void main(String[] args) {
        System.out.println("========类适配器模式=========");
        Phone phone = new Phone();
        phone.charging(new VoltageAdapter());
//        ========类适配器模式=========
//        220V已经适配成5V啦!可以充电啦!
//        电压为5V~可以充电
    }
}

java是单继承模式,这里适配器继承了220V直流,实现了5V交流接口,接口可以是很多个,但是只能继承一个。
我们继承220V直流的目的时什么?
就是想用他里边的output220V这个方法,然后通过一顿操作将他改成5V直流。根据合成符用原则,如果B类仅仅想使用A类中的方法,我们尽量使用组合和聚合的方式,而不是通过继承。继承带来的后果就是:侵入性,不够灵活,高耦合。
所以我们能用组合和聚合就不要使用继承。
所以我们引出对象适配器模式

2.对象适配器模式

我们只需要把220V直流那个类聚合到适配器类里边就ok了。
类图
在这里插入图片描述
新的适配器类

package com.jc.adapter.objectadapter;

/**
* @program: 设计模式
*
* @description: 适配器
*
* @author: Mr.Wang
*
* @create: 2021-06-16 20:05
**/
public class VoltageAdapter implements Voltage5V {
	//聚合进来
    Voltage220V voltage220V;

    public VoltageAdapter(Voltage220V voltage220V) {
        this.voltage220V = voltage220V;
    }

    @Override
    public int output5V() {
        int src = voltage220V.output220V();

        src = src / 44;
        System.out.println("220V已经适配成5V啦!可以充电啦!");

        return src;
    }
}

Client

package com.jc.adapter.objectadapter;

import jdk.internal.dynalink.beans.StaticClass;

import java.util.*;

/**
* @program: 设计模式
*
* @description: 
*
* @author: Mr.Wang
*
* @create: 2021-06-16 20:08
**/
public class Client {
    public static void main(String[] args) {
        System.out.println("========对象适配器模式=========");
        Phone phone = new Phone();
        phone.charging(new VoltageAdapter(new Voltage220V()));
//        ========对象适配器模式=========
//        220V已经适配成5V啦!可以充电啦!
//        电压为5V~可以充电
    }
}

依然可以实现相同效果,相比于类适配器更加灵活,耦合性低

3.接口适配器模式

1.接口适配器模式又被称为 缺省适配器模式
2.当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求

类图

这里是引用

Interface4

package com.jc.adapter.interfaceadapter;

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

AbstractAdapter

package com.jc.adapter.interfaceadapter;/**
* @program: 设计模式
*
* @description: 
*
* @author: Mr.Wang
*
* @create: 2021-06-17 21:54
**/
public abstract class AbstractAdapter implements Interface4 {
    @Override
    public void m1() {

    }

    @Override
    public void m2() {

    }

    @Override
    public void m3() {

    }

    @Override
    public void m4() {

    }

    @Override
    public void m5() {

    }
}

ConcreteAdapter1

package com.jc.adapter.interfaceadapter;/**
* @program: 设计模式
*
* @description: 
*
* @author: Mr.Wang
*
* @create: 2021-06-17 21:59
**/
public class ConcreteAdapter1 extends AbstractAdapter {
    @Override
    public void m1() {
        System.out.println("第一个适配器:我要用m1 所以实现了m1");
    }
    public ConcreteAdapter1(){
        System.out.println("=====我是第一个适配器====我只实现了m1,m3");
    }

    @Override
    public void m3() {
        System.out.println("第一个适配器:我要用m3 所以实现了m3");
    }
}

ConcreteAdapter2

package com.jc.adapter.interfaceadapter;/**
* @program: 设计模式
*
* @description: 
*
* @author: Mr.Wang
*
* @create: 2021-06-17 21:59
**/
public class ConcreteAdapter2 extends AbstractAdapter {


    public ConcreteAdapter2(){
        System.out.println("=====我是第二个适配器====我只实现了m2,m4");
    }
    @Override
    public void m2() {
        System.out.println("第二个适配器:我要用m2 所以实现了m2");
    }

    @Override
    public void m4() {
        System.out.println("第二个适配器:我要用m4 所以实现了m4");
    }
}

Client

package com.jc.adapter.interfaceadapter;/**
* @program: 设计模式
*
* @description: 
*
* @author: Mr.Wang
*
* @create: 2021-06-17 21:54
**/
public class Client {
    public static void main(String[] args) {
        //第一个适配器
        AbstractAdapter adapter1 = new ConcreteAdapter1();
        adapter1.m1();
        adapter1.m3();

        //第二个适配器
        AbstractAdapter adapter2 = new ConcreteAdapter2();
        adapter2.m2();
        adapter2.m4();
//        =====我是第一个适配器====我只实现了m1,m3
//        第一个适配器:我要用m1 所以实现了m1
//        第一个适配器:我要用m3 所以实现了m3
//        =====我是第二个适配器====我只实现了m2,m4
//        第二个适配器:我要用m2 所以实现了m2
//        第二个适配器:我要用m4 所以实现了m4
    }
}

通过打印结果我们实现了自己想要的适配器,并实现了自己的操作。

在源码中应用

1.HttpServlet继承GenericServlet,GenericServlet空实现于javax.servlet.Servlet
在这里插入图片描述
2.在springMVC框架中的应用

这里是引用
HandlerAdapter

public interface HandlerAdapter {
    boolean supports(Object var1);
    @Nullable
    ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
    long getLastModified(HttpServletRequest var1, Object var2);
}

HttpRequestHandlerAdapter (其中一个具体的适配器)

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

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

    @Nullable
    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;
    }
}

如何应用的?

DispatchServlet中的doDispatch方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
     
        //根据HandlerMapping获取对应的Handler(Controller)
        mappedHandler = this.getHandler(processedRequest);
        //没有根据映射拿到Handler的话报错。
         if (mappedHandler == null) {
               this.noHandlerFound(processedRequest, response);
               return;
           }
		//从handlerAdapters选择一个支持具体的Hander的适配器
	   HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
     
             
		//根据适配器进行处理,然后返回结果.
	  mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
	}

getHandlerAdapter方法

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
    	//遍历handlerAdapters选择合适的HandlerAdapter 
        for (HandlerAdapter adapter : this.handlerAdapters) {
            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、将目标类和适配者类解耦,(譬如上边的,将DispatchServlet和具体的适配器解耦)
2、增加了类的透明性和复用性将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性
3、灵活性和扩展性都非常好,符合开闭原则

不好:
适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂
降低代码可读性,过多使用适配器会使系统代码变得很难懂

标签:实例,adapter,5V,public,源码,void,println,适配器
来源: https://blog.csdn.net/daniu_weilai/article/details/120812477

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有