适配器模式

适配器模式概述

  1. 什么是适配器模式:假设想要调用A类中的某个方法,但是该方法需要一个B类型的参数,而A类中只能拿到A类型的参数,将A类型的参数合理的转换为B类型的参数,这个转换过程就可以成为适配,总结来说: 让原本不能匹配的接口可以协同工作
  2. 适配器模式属于接口模式,注意分为三类: 类适配器, 对象适配器, 接口适配器

一. 类适配器模式

案例: 给手机充电,手机为调用方,充电器为适配器接口, 输出220v电压插座为被支配者接口

实现要点

通过创建中间适配器类,进行适配,手机充电需要调用5V接口,而现在只有输出220V的Socket, 创建中间适配器接口,创建适配器类,适配器类继承输出220V的Socket,可以拿到输出220V的方法,并且实现适配器接口Ivoltage5v,重写抽象方法,在方法中调用Socket输出220v的方法,降压后输出

代码示例

  1. 被适配方
//被适配方,输出220V电压
class Socket{
	//该接口输出220V电压
	public Integer outPut220v(){
		System.out.println("输出220V电");
		return 220;
	}
}
  1. 适配接口
//适配接口
interface Ivoltage5v {
	public Integer output5v();
}
  1. 适配器
//适配器继承被适配方Socket,
class VoltageAdapter extends Socket implements Ivoltage5v{
	//适配方法,通过继承可以获取到Socket输出220的方法,通过
	//适配方法降压为5v输出
	@Override
	public Integer output5v() {
		Integer srcV = super.outPut220v();
		System.out.println("通过类适配器降压");
		return srcV/44;
	}
}
  1. 调用方
//调用方: 手机充电
class Phone{
	//调用充电方法,但是输出220V的不适用
	public void charging(Ivoltage5v voltager) {
		Integer v = voltager.output5v();
		System.out.println("给手机充电"+v);
	}
}
  1. 测试
public class AdapterTest {
	public static void main(String[]args) {
		Phone p = new Phone();
		Ivoltage5v voltager = new VoltageAdapter();
		p.charging(voltager);
	}
}

分析类适配器模式

  1. 对类适配器模式我的理解是: 创建适配接口Ivoltage5v ,提供适配方法output5v(),创建适配器类VoltageAdapter 实现适配接口,并继承定义了需要调用但不适配的方法的类Socket ,需要调用Socket 中的 outPut220v()方法,但是该方法返回的参数是220,重写适配接口中的适配方法output5v(),在方法中通过子类继承父类的关系,使用super调用Socket 中原本不适用的方法,获取该方法返回的值,然后在适配方法中根据需求对父类方法返回的值进行修改适配,在后续调用时直接调用适配方法即可
  2. 通过继承被适配方,可以拿到被适配方的方法,进行重写被适配比较灵活
  3. 被适配方与适配器适配后的方法都需要暴露出来运行外部继承调用
  4. java是单继承,通过类适配器进行适配需要继承被适配方,拿到原有的需要进行适配的方法,局限性

二. 对象适配器模式

什么是对象适配器

根据"合成复用原则" 在类适配器模式上进行修改,使原本创建中间适配器不再通过继承方法获取原有被适配方的方法,而是通过适配器中持有聚合一个被适配方的对象,实现适配接口时通过持有的被适配对象调用需要适配的方法,解决了类适配器模式需要适配器继承被适配者的局限性(也就是在适配器类VoltageAdapter 中,定义一个被适配对象的属性Socket,重写适配方法时通过该属性对象调用需要适配的方法)

代码示例

修改原有适配器,将通过继承模式拿到被适配者,修改为:适配者持有聚合一个被适配者,通过聚合进来的被适配者拿到需要适配的方法

  1. 适配器
//适配器持有被适配者
class VoltageAdapter implements Ivoltage5v{
	private Socket socket;
	//通过构造器或者提供set方法,对持有的Socket赋值
	public VoltageAdapter(Socket socket) {
		this.socket = socket;
	}
	
	//适配方法:通过持有的socket实例,调用被适配者方法
	@Override
	public Integer output5v() {
		Integer srcV = socket.outPut220v();
		System.out.println("通过类适配器降压");
		return srcV/44;
	}
}
  1. 测试
public class AdapterTest {
	public static void main(String[]args) {
		Phone p = new Phone();
		//适配者持有被适配者,创建被适配者对象
		Socket socket = new Socket();
		//通过VoltageAdapter构造器赋值给注入进来的被适配者
		Ivoltage5v voltager = new VoltageAdapter(socket);
		p.charging(voltager);
	}
}

三. 接口适配器模式

什么是接口适配器模式: 假设接口中的某个方法不适用,需要重写,但是并不希望全部重写,在调用时除了指定的方法外,其它方法还希望使用接口中原有的,创建一个实现该接口的抽象子类,抽象子类中对于不适配的方法进行重写,在调用的该不适用的方法时使用抽象子类去调用,或者不重写,在使用到该方法时通过创建抽象类对象,在{中进行重写},例如m1,与m2方法

代码示例

  1. 接口
interface AdapterInterface{
	//假设接口中的m1方法并不适用
	void m1();
	void m2();
	void m3();
}
  1. 创建抽象类,抽象类继承接口
abstract class AbsAdapter implements AdapterInterface{
	//假设接口中的m1方法并不适用
	//@Override
	//public void m1() { };
	@Override
	public void m2() {
		System.out.println("m2方法执行");
	};
	@Override
	public void m3() { };
}
  1. 在调用m1方法时可以通过匿名类的方式冲向m1方法,根据需求自己实现
public class AdapterTest {
	public static void main(String[]args) {
		AbsAdapter a = new AbsAdapter() {
			//重写AbsAdapter中的m1方法
			@Override
			public void m1() {
				System.out.println("接口适配器模式");
			}
		};
		//m1方法为重写的方法
		a.m1();
		//m2方法为抽象类中的
		a.m2();
	}
}

Spring框架适配器模式适用案例

  1. 在SpringMVC中的 HandlerAdapter,
  1. 复习SpringMVC: Spring的web.xml中有DispathcerServlet前端控制器,该类中加载了关于mvc的xml配置文件,并指定拦截所有请求,将所有请求都交给DispatcherServlet,通过DispatcherServlet初始化servlet 截获符合特定格式的URL请求。初始化DispatcherServlet上下文对应的WebApplicationContext,并将其与业务层、持久化层的WebApplicationContext建立关联。初始化Spring MVC的各个组成组件,并装配到DispatcherServlet中
  2. SpringMVC处理一次请求的执行流程: 用户发送请求,创建DispathcerServlet前端控制器对象,将所有请求交给该对象处理,通过DispathcerServlet对象将请求分发给处理器HandlerMapping,通过HandlerMapping进行映射请求地址与Controller方法, DispathcerServlet将请求交给Controller,Conrtoller进行业务处理后,将处理结果存入ModelAndView对象中, DispatcherServlet查询多个ViewResoler视图解析器,找到对应的ModelAndView指定视图,将视图返回给用户,(发送请求时会通过DispathcerServlet对象调用doService方法,该方法中会根据请求路径获取处理器映射器HandlerMapping,HandlerMapping对象调用getHandler()方法,获取到到对应的Handler(也就是请求路径对应的controller方法),如果不存在则调用sendError方法,报404,存在则通过Handler对象调用handle()方法,执行路径对应的controller方法,执行完毕后,会通过ViewResolver视图转换器(视图解析器Springmvc配置文件中的),找到对应的ModleandView返回给客户端)
  3. 在获取处理器映射器HandlerMapping时就是通过适配器模式设计的,HandlerMapping调用getHandler()方法返回的数据会通过getHandlerAdapter()方法与自己的进行适配,适配不成功则返回false
  1. 在SpringAOP中的AdvisorAdapter接口就是一个适配器,该接口中的“MethodInterceptor getInterceptor(Advisor var1)”方法就是用来适配的方法,在该接口的实现类中,例如MethodBeforeAdviceAdapter中,对该方法进行了重写
  2. 在jpa中 JpaVendorAdapter ,该接口也是一个适配器,该接口中的方法通过子类重写进行适配,跟据连接数据库的不同适配进行不同的适配

业务与设计模式落地示例

  1. 在很多网站上,用户可以通过第三方授权登录(如微信、QQ、微博等)来进行注册和登录。每种第三方授权登录都有自己的API,因此需要使用适配器设计模式来封装不同授权登录的API,以适应系统的登录接口
  2. 定义抽象接口,表示系统对外提供的登录接口。这里假设系统提供了一个统一的登录接口login(String username, String password)来实现用户登录功能
public interface AuthService {
    boolean login(String username, String password);
}
  1. 实现一个第三方登录适配器,用于将各个第三方登录API进行适配,其中ThirdPartyAuthService表示第三方登录服务,其内部实现了具体的第三方登录API
public class ThirdPartyAuthAdapter implements AuthService {

    private ThirdPartyAuthService thirdPartyAuthService;

    public ThirdPartyAuthAdapter(ThirdPartyAuthService thirdPartyAuthService) {
        this.thirdPartyAuthService = thirdPartyAuthService;
    }

    @Override
    public boolean login(String username, String password) {
        // 调用第三方登录API进行用户认证
        return thirdPartyAuthService.auth(username, password);
    }
}
  1. 对外接口示例
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);

        // 创建第三方登录适配器实例
        ThirdPartyAuthService qqAuthService = new QQAuthService();
        AuthService authService = new ThirdPartyAuthAdapter(qqAuthService);

        // 使用适配器进行登录
        boolean result = authService.login("user_name", "password");
        if (result) {
            System.out.println("登录成功");
        } else {
            System.out.println("登录失败");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值