1.什么是适配器模式?
适配器模式是一种结构型设计模式。
适配器模式的思想是:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
2.适配器模式的优缺点
优点
1.更好的复用性:系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
2.更好的扩展性:在实现适配器功能的时候,可以扩展自己源的行为(增加方法),从而自然地扩展系统的功能。
缺点
1.会导致系统紊乱:滥用适配器,会让系统变得非常凌乱。
2.适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性。
3.增加代码阅读难度,降低代码可读性。
例如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
3.适配器模式的使用场景
1.springmvc多个不同controller实现;
2.API多版本控制
3.旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,但我们不希望手动更改原有类的时候
4…使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。
5.类所做的事情相同或相似,但是具有不同接口的时候
4.适配器模式的定义
5.适配器模式的架构图
6.案例(不同版本的Api接口)
6.1 创建第一个版本的Api接口及实现类
package com.xhs.pattern.adapter.service;
/**
* @desc:
* @author: xhs
* @date: 2022/6/22 9:41
* @version: JDK 1.8
*/
public interface ApiV1Service {
/**
* 获取用户信息
*
* @return
*/
Object getInfo();
}
实现类
package com.xhs.pattern.adapter.service.impl;
import com.xhs.pattern.adapter.service.ApiV1Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @desc: v1版本接口的实现类
* @author: xhs
* @date: 2022/6/22 9:42
* @version: JDK 1.8
*/
@Slf4j
@Service(("V1"))
public class ApiV1ServiceImpl implements ApiV1Service {
@Override
public Object getInfo() {
log.info(">>>>>>>>>>>>>>>>v1版本接口的实现类<<<<<<<<<<<<<<<<<<<<<<");
return "v1版本接口的实现类";
}
}
6.2 创建第二个版本的Api接口及实现类
接口参数可以随便改
package com.xhs.pattern.adapter.service;
/**
* @desc:
* @author: xhs
* @date: 2022/6/22 9:41
* @version: JDK 1.8
*/
public interface ApiV2Service {
/**
* 获取用户信息
*
* @return
*/
Object getInfo();
}
实现类
package com.xhs.pattern.adapter.service.impl;
import com.xhs.pattern.adapter.service.ApiV2Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @desc: v2版本接口的实现类
* @author: xhs
* @date: 2022/6/22 9:42
* @version: JDK 1.8
*/
@Slf4j
@Service("V2")
public class ApiV2ServiceImpl implements ApiV2Service {
@Override
public Object getInfo() {
log.info(">>>>>>>>>>>>>>>>v2版本接口的实现类<<<<<<<<<<<<<<<<<<<<<<");
return "v2版本接口的实现类";
}
}
6.3 创建适配器ApiAdapter
package com.xhs.pattern.adapter.adapter;
import javax.servlet.http.HttpServletRequest;
/**
* @desc: 适配器
* @author: xhs
* @date: 2022/6/22 9:28
* @version: JDK 1.8
*/
public interface ApiAdapter {
/**
* 判断具体实现类 到底是什么类型 通过该类型 查找到具体的适配器
* @param object
* @return
*/
boolean supports(Object object);
/**
* 不同实现类的具体实现
* @param httpServletRequest
* @param object
*/
Object handle(HttpServletRequest httpServletRequest, Object object);
}
6.4 创建2个版本的适配器实现类
package com.xhs.pattern.adapter.adapter.impl;
import com.xhs.pattern.adapter.adapter.ApiAdapter;
import com.xhs.pattern.adapter.service.ApiV1Service;
import javax.servlet.http.HttpServletRequest;
/**
* @desc: v1版本的接口
* @author: xhs
* @date: 2022/6/22 9:35
* @version: JDK 1.8
*/
public class ApiV1AdapterImpl implements ApiAdapter {
@Override
public boolean supports(Object object) {
return object instanceof ApiV1Service;
}
@Override
public Object handle(HttpServletRequest httpServletRequest, Object object) {
ApiV1Service apiV1Service = (ApiV1Service) object;
Object info = apiV1Service.getInfo();
return info;
}
}
package com.xhs.pattern.adapter.adapter.impl;
import com.xhs.pattern.adapter.adapter.ApiAdapter;
import com.xhs.pattern.adapter.service.ApiV2Service;
import javax.servlet.http.HttpServletRequest;
/**
* @desc:
* @author: xhs
* @date: 2022/6/22 9:47
* @version: JDK 1.8
*/
public class ApiV2AdapterImpl implements ApiAdapter {
@Override
public boolean supports(Object object) {
return object instanceof ApiV2Service;
}
@Override
public Object handle(HttpServletRequest httpServletRequest, Object object) {
ApiV2Service apiV2Service = (ApiV2Service) object;
Object info = apiV2Service.getInfo();
return info;
}
}
6.5 创建获取适配器及调用具体版本的Api的方法
package com.xhs.pattern.adapter.adapter.impl;
import com.xhs.pattern.adapter.adapter.ApiAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
/**
* @desc:
* @author: xhs
* @date: 2022/6/22 10:28
* @version: JDK 1.8
*/
@Slf4j
@Service
public class ApiAdapterImpl {
private List<ApiAdapter> adapterList = new ArrayList<>();
/**
* 添加每一种 方式实现的适配器
*/
public ApiAdapterImpl() {
adapterList.add(new ApiV1AdapterImpl());
adapterList.add(new ApiV2AdapterImpl());
}
/**
* 执行Api具体的实现方法
*
* @param httpServletRequest
* @param object
*/
public Object doService(HttpServletRequest httpServletRequest, Object object) {
ApiAdapter apiAdapter = getApiAdapter(object);
Object handle = apiAdapter.handle(httpServletRequest, object);
return handle;
}
/**
* 获取到该Api的具体适配器
*
* @param object
* @return
*/
public ApiAdapter getApiAdapter(Object object) {
for (ApiAdapter adapter : adapterList) {
if (adapter.supports(object)) {
return adapter;
}
}
return null;
}
}
6.6 创建测试的controller进行验证
package com.xhs.pattern.adapter.controller;
import com.xhs.pattern.adapter.adapter.impl.ApiAdapterImpl;
import com.xhs.pattern.dto.request.GetInfoRequest;
import com.xhs.pattern.utils.SpringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @desc: 适配器模式
* @author: xhs
* @date: 2022/6/22 9:27
* @version: JDK 1.8
*/
@RestController
@RequestMapping("/adapter")
public class AdapterController {
@Autowired
private ApiAdapterImpl apiAdapter;
@RequestMapping("/getInfo")
public String getInfo(@RequestBody GetInfoRequest infoRequest) {
String adapter = infoRequest.getAdapter();
Object object = SpringUtils.getBean(adapter);
Object service = apiAdapter.doService(null, object);
return service.toString();
}
}