设计模式的实际应用
设计模式的实际应用
丑陋的代码
- 业务常见描述
项目中需要根据配置的不同的云存储来判断最终需要将文件上传到哪一个云存储服务,于是原来的代码是这么写的
//是否是阿里云
if (是阿里云) {
cloudStorageResult = FileUploadCloudStorageUtils.uploadFile2AliOSSCloudStorage(fileName, outPath, generationRecord, excelJson.getExpireDays());
}
//是否是微软云
if (是微软云) {
cloudStorageResult = FileUploadCloudStorageUtils.uploadFile2AzureBlobCloudStorage(fileName, outPath, generationRecord);
}
//是否是亚马逊云
if (是亚马逊云) {
cloudStorageResult = FileUploadCloudStorageUtils.uploadFile2AwsS3CloudStorage(fileName, outPath, generationRecord);
}
//是否是腾讯云
if (CloudStorageEnvConfig.isIsCos()) {
cloudStorageResult = FileUploadCloudStorageUtils.uploadFile2CosClientCloudStorage(fileName, outPath, generationRecord);
}
//华为云
if (华为云) {
cloudStorageResult = FileUploadCloudStorageUtils.uploadFile2ObsClientCloudStorage(fileName, outPath, generationRecord, String.valueOf(excelJson.getExpireDays()));
}
如果再来几个人,那么凡事用到上传地方都必须要在添加代码。这还不说,这样写代码看起来是不是很low?
引入设计模式
使用策略模式+工厂模式进行重构
- 定义策略模式的接口
public interface CloudStorageStrategyService {
/**
* 上传云存储方法
*
* @param cloudStorageEntity 云存储参数对象实体
* @return CloudStorageResult 上传后的结果
*/
CloudStorageResult uploadCloudStorage(CloudStorageEntity cloudStorageEntity);
}
- 阿里云存储的实现类
@Service
public class AliOssCloudStorageStrategyServiceImpl implements CloudStorageStrategyService {
@Override
public CloudStorageResponse.CloudStorageResult uploadCloudStorage(CloudStorageEntity cloudStorageEntity) {
return FileUploadCloudStorageUtils.uploadFile2AliOSSCloudStorage(cloudStorageEntity.getFileName(),
cloudStorageEntity.getOutPath(),
cloudStorageEntity.getGenerationRecord(),
cloudStorageEntity.getExpireDays());
}
}
- 亚马逊云存储
@Service
public class AwsS3CloudStorageStrategyServiceImpl implements CloudStorageStrategyService {
@Override
public CloudStorageResponse.CloudStorageResult uploadCloudStorage(CloudStorageEntity cloudStorageEntity) {
return FileUploadCloudStorageUtils.uploadFile2AwsS3CloudStorage(cloudStorageEntity.getFileName(),
cloudStorageEntity.getOutPath(),
cloudStorageEntity.getGenerationRecord(),
cloudStorageEntity.getExpireDays());
}
}
其他的类似 就不一一列举,列举两个就已经有多个的代表性了
- 但是接口的对应是实例该则呢吗返回呢?那就是通过工厂模式来返回对应的实例
@Component
public class CloudStorageFactory {
@Autowired
private AliOssCloudStorageStrategyServiceImpl aliOssCloudStorageStrategyService;
@Autowired
private AwsS3CloudStorageStrategyServiceImpl awsS3CloudStorageStrategyService;
@Autowired
private AzureCloudStorageStrategyServiceImpl azureCloudStorageStrategyService;
@Autowired
private CosCloudStorageStrategyServiceImpl cosCloudStorageStrategyService;
@Autowired
private ObsCloudStorageStrategyServiceImpl obsCloudStorageStrategyService;
@Autowired
private ObsInnerCloudStorageStrategyServiceImpl obsInnerCloudStorageStrategyService;
public CloudStorageStrategyService getInstance() {
//获取云存储类型枚举对象
CloudStorageEnum cloudStorageEnum = CloudStorageUtils.getCloudStorageEnum();
//获取阿里云存储的单例对象
if (cloudStorageEnum.equals(CloudStorageEnum.AliOSS)) {
return aliOssCloudStorageStrategyService;
}
//获取微软云存储的单例对象
else if (cloudStorageEnum.equals(CloudStorageEnum.AZURE)) {
return azureCloudStorageStrategyService;
}
//获取亚马逊云存储的单例对象
else if (cloudStorageEnum.equals(CloudStorageEnum.AWS)) {
return awsS3CloudStorageStrategyService;
}
//获取腾讯云存储的单例对象
else if (cloudStorageEnum.equals(CloudStorageEnum.COS)) {
return cosCloudStorageStrategyService;
}
//获取华为云存储的单例对象
else if (cloudStorageEnum.equals(CloudStorageEnum.OBS)) {
return obsCloudStorageStrategyService;
}
//获取华为云存储内网专用的单例对象
else if (cloudStorageEnum.equals(CloudStorageEnum.OBS_INNER)) {
return obsInnerCloudStorageStrategyService;
}
//默认返回阿里云存储对象
return aliOssCloudStorageStrategyService;
}
}
本来所有的策略模式的实现类是没有交给Spring管理的,都是写的单例模式返回的单例。但是既然使用到框架了,那我们就把对象交给框架来管理吧,这里重点是将代码重构,这样子在调用的时候就直接通过如下方式
//通过工厂模式返回对应云存储类型的对象
CloudStorageStrategyService cloudStorageStrategyService = cloudStorageFactory.getInstance();
//云存储参数的实例对象
CloudStorageEntity cloudStorageEntity = new CloudStorageEntity();
cloudStorageResult = cloudStorageStrategyService.uploadCloudStorage(cloudStorageEntity);