适配器模式
一、什么是适配器模式
适配器模式是一种结构型设计模式,它允许将不兼容的对象转换成可兼容的接口。主要目的是解决在不改变现有代码的情况下,使不兼容的接口之间能够正常工作,通过创建一个中间转换的适配器来将一个对象转换成我们所需要的接口。
二、角色组成
目标接口(target):需要适配的标准接口。
源对象(source):需要被适配的不兼容对象。
适配器对象(adapter):充当中间转换角色,该对象将源对象转换成目标接口。
三、优缺点
优点:
安全可靠:封装了旧接口,对客户端透明,客户端代码无需修改。
提高复用性:可以复用不兼容的类;可以对不同的类无需修改,就可以进行组合。
扩展性好:在应用程序开发过程中,可以增加新的适配器和被适配对象。
缺点:
过多的适配器会导致系统结构复杂。如果适配器没有实现好,可能会拖慢整个系统的性能。
滥用适配器模式会导致系统设计紊乱。
四、应用场景
4.1 生活场景
电压转换器:不同国家的电压规格各异,同样功率的电器在不同的地方工作时需要不同的电压,电压转换器作为适配器,将不同电压转换成电器使用标准电压。
耳机转接头:有些手机没有耳机插口,需要使用转接头适配器,将耳机转换为手机支持的接口,实现对不同的耳机兼容。
4.2 java场景
JDBC驱动程序:不同的数据库提供商实现了不同的JDBC驱动接口,使用适配器模式可以将这些不同的接口适配为标准的JDBC接口,提高应用程序的可移植性。
日志框架:Java中有多个常用的日志框架,如Log4j、SLF4J等,不同的日志框架提供的API不同,使用适配器模式可以将这些不同的API适配为一个统一的接口,方便再程序中进行日志记录和管理。
第三方库或SDK:在使用第三方库或 SDK 时,可能由于它们实现的 API 不同而导致应用程序复杂,使用适配器模式可以将不同的 API 适配为统一的接口,简化应用程序的调用。
五、代码实现
@RestController
public class FileController {
@Resource
private FileService fileService;
@RequestMapping("/getUrl")
public String getUrl(String bucketName, String objectName) throws Exception {
return fileService.getUrl(bucketName, objectName);
}
/**
* 上传文件
*/
@RequestMapping("/upload")
public Result upload(MultipartFile uploadFile, String bucket, String objectName) throws Exception {
String url = fileService.uploadFile(uploadFile, bucket, objectName);
return Result.ok(url);
}
@RequestMapping("/testGetAllBuckets")
public String testGetAllBuckets() throws Exception{
List<String> allBucket = fileService.getAllBucket();
return allBucket.get(0);
}
}
/**
* 文件存储service
*
*/
@Service
public class FileService {
private final StorageAdapter storageAdapter;
public FileService(StorageAdapter storageAdapter) {
this.storageAdapter = storageAdapter;
}
/**
* 列出所有桶
*/
public List<String> getAllBucket() {
return storageAdapter.getAllBucket();
}
/**
* 获取文件路径
*/
public String getUrl(String bucketName,String objectName) {
return storageAdapter.getUrl(bucketName,objectName);
}
/**
* 上传文件
*/
public String uploadFile(MultipartFile uploadFile, String bucket, String objectName){
storageAdapter.uploadFile(uploadFile,bucket,objectName);
objectName = objectName + "/" + uploadFile.getOriginalFilename();
return storageAdapter.getUrl(bucket, objectName);
}
}
/**
* 文件存储适配器
*
*/
public interface StorageAdapter {
/**
* 创建bucket桶
*/
void createBucket(String bucket);
/**
* 上传文件
*/
void uploadFile(MultipartFile uploadFile, String bucket, String objectName);
/**
* 列出所有桶
*/
List<String> getAllBucket();
/**
* 列出当前桶及文件
*/
List<FileInfo> getAllFile(String bucket);
/**
* 下载文件
*/
InputStream downLoad(String bucket, String objectName);
/**
* 删除桶
*/
void deleteBucket(String bucket);
/**
* 删除文件
*/
void deleteObject(String bucket, String objectName);
String getUrl(String bucket, String objectName);
}
/**
* 阿里云oss适配器
*
*/
public class AliStorageAdapter implements StorageAdapter {
@Override
public void createBucket(String bucket) {
}
@Override
public void uploadFile(MultipartFile uploadFile, String bucket, String objectName) {
}
@Override
public List<String> getAllBucket() {
List<String> bucketNameList = new LinkedList<>();
bucketNameList.add("aliyun");
return bucketNameList;
}
@Override
public List<FileInfo> getAllFile(String bucket) {
return null;
}
@Override
public InputStream downLoad(String bucket, String objectName) {
return null;
}
@Override
public void deleteBucket(String bucket) {
}
@Override
public void deleteObject(String bucket, String objectName) {
}
@Override
public String getUrl(String bucket, String objectName) {
return null;
}
}
/**
* minioIO存储适配器
*
*/
public class MinioStorageAdapter implements StorageAdapter {
@Resource
private MinioUtil minioUtil;
/**
* minioUrl
*/
@Value("${minio.url}")
private String url;
@Override
@SneakyThrows
public void createBucket(String bucket) {
minioUtil.createBucket(bucket);
}
@Override
@SneakyThrows
public void uploadFile(MultipartFile uploadFile, String bucket, String objectName) {
minioUtil.createBucket(bucket);
if (objectName != null) {
minioUtil.uploadFile(uploadFile.getInputStream(), bucket, objectName + "/" + uploadFile.getOriginalFilename());
} else {
minioUtil.uploadFile(uploadFile.getInputStream(), bucket, uploadFile.getOriginalFilename());
}
}
@Override
@SneakyThrows
public List<String> getAllBucket() {
return minioUtil.getAllBucket();
}
@Override
@SneakyThrows
public List<FileInfo> getAllFile(String bucket) {
return minioUtil.getAllFile(bucket);
}
@Override
@SneakyThrows
public InputStream downLoad(String bucket, String objectName) {
return minioUtil.downLoad(bucket, objectName);
}
@Override
@SneakyThrows
public void deleteBucket(String bucket) {
minioUtil.deleteBucket(bucket);
}
@Override
@SneakyThrows
public void deleteObject(String bucket, String objectName) {
minioUtil.deleteObject(bucket, objectName);
}
@Override
@SneakyThrows
public String getUrl(String bucket, String objectName) {
return url + "/" + bucket + "/" + objectName;
}
}
/**
* 文件存储config
*
*/
@Configuration
@RefreshScope
public class StorageConfig {
@Value("${storage.service.type}")
private String storageType;
@Bean
@RefreshScope
public StorageAdapter storageService() {
if ("minio".equals(storageType)) {
return new MinioStorageAdapter();
} else if ("aliyun".equals(storageType)) {
return new AliStorageAdapter();
} else {
throw new IllegalArgumentException("未找到对应的文件存储处理器");
}
}
}
storage:
service:
type: aliyun

浙公网安备 33010602011771号