把策略模式应用到实际项目中

栏目: 后端 · 发布时间: 5年前

内容简介:无论你知不知道这个设计模式,但必定在项目中都似曾相识。倘若仅仅聊理论必然枯燥乏味,只有理论和实战相结合方可达到人剑合一的境界。首先,我来说个需求,倘若是你遇到该如何做?你可停留几分钟,想出你的解决方式,可在下方留言,说出你的想法。

把策略模式应用到实际项目中

无论你知不知道这个设计模式,但必定在项目中都似曾相识。倘若仅仅聊理论必然枯燥乏味,只有理论和实战相结合方可达到人剑合一的境界。

首先,我来说个需求,倘若是你遇到该如何做?你可停留几分钟,想出你的解决方式,可在下方留言,说出你的想法。

需求

用户有文件上传的需求,而我们要负责对文件进行存储,由于我们的系统可能会单独给个别客户私有化部署(部署尽量少依赖中间件能服务等),同时我们也会自己运营成为自己的SaaS服务(保证服务的高可用等)。

所以我们有两点需求:

1. 要在SaaS版本中将文件存入分布式存储系统fastDfs中

2. 客户的私有部署中 将文件 存储在数据库中

思路

寻找异同点

  • 文件上传过程这个无论什么版本部署都是一样的,所以暂不考虑。

  • 文件存储的方式不同,同时文件的获取和删除也不同

  • 保存,获取,删除后的响应也是相同的,也不考虑了。

开始抽象

当前我们考虑的就是文件的存储,获取和删除。同样的行为,不同的实现,我们必定想到定义一个接口:

/**
* 文件存储接口
* Identify表示文件的唯一标识,可任意类型
* T 表示 上传下载的返回类型,可任意类型
*
* @author flyhero
* @date 2019-02-01 11:18 AM
*/
public interface IStorageService<Identify, T> {
 
/**
* 上传文件
*
* @param file
* @return
*/
T upload(MultipartFile file);
 
/**
* 下载文件
*
* @param identify
* @return
*/
T download(Identify identify);
 
/**
* 删除文件
*
* @param identify
*/
void delete(Identify identify);
}

两种不同的实现

  • 存储FastDfs

@Slfj
@Service("fastDfsServiceImpl")
public class FastDfsServiceImpl implements IStorageService<String,FileVo> {
 
@Override
@Transactional(rollbackFor = Exception.class)
public FileVo upload(MultipartFile multipartFile){
logger.info("存储在fastDfs……");
}
 
@Override
public FileVo download(String hash) {
logger.info("从fastDfs下载文件");
return null;
}
 
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(String hash) {
logger.info("从fastDfs删除文件");
}
}
  • 存储 数据库

@Slfj
@Service("databaseServiceImpl")
public class DatabaseServiceImpl implements IStorageService<String,FileVo> {
 
@Override
@Transactional(rollbackFor = Exception.class)
public FileVo upload(MultipartFile file) {
logger.info("存储在database……");
return null;
}
 
@Override
public FileVo download(String hash) {
logger.info("从database下载文件");
return null;
}
 
@Override
public void delete(String hash) {
logger.info("从database删除文件");
}
}
  • 调用

@Service
public class FileServiceImpl implements FileService {
 
//  同一个接口根据不同的名称调用不同的实现
//  @Qualifier("databaseServiceImpl")
@Qualifier("fastDfsServiceImpl")
@Autowired
private IStorageService storageService;
 
public void save(MultipartFile file){
if (null == file) {
throws new Exception("文件不能为空");
}
FileVo fileVo = storageService.upload(file);
}
}

疑惑

可能有人会说了:这怎么和我了解的策略模式不一样啊,策略模式不是这样的吗?

把策略模式应用到实际项目中

你说的对!但这是在没有任何框架下的设计模式,而我们现在普遍使用的都是Spring框架,那么标准的策略模式中的Context去哪里了?

  • 引入Context的作用

首先我们要知道 引入Context的作用,是 为了避免高层直接与策略接口直接交互 ,为什么呢?因为我们策略模式接口功能相对比较单一,而有些高层模块可能需要一些比较复杂的交互。

1.若直接调用接口,则需要对每个实现增加逻辑;

2.若直接调用前,执行增强逻辑,那么多个地方使用时,会存在重复增强逻辑,并可能忘掉。

此时引入Context是解决问题的最佳方式。

而我们的FileServiceImpl就相当于Context的作用,由于我们使用Spring框架且使用了三层架构,暴露上传文件、下载文件、删除文件是在controller层三个不同的方法中(或不同的controller中),为了避免几个地方使用的存储策略不同,我直接在Context中来指定使用的策略,当需要切换时也非常方便,只需要更改IStorageService的注解即可。

总结

优点

  • 策略实现类可自由切换

  • 易于扩展,若还有新的策略只要新增策略接口一个实现类即可

  • 不必使用条件语句进行决定使用哪个策略

缺点

  • 策略类一旦增多,调用者要清楚的知道各种策略的区别

如果你有不同的看法,还望不吝指教。

海内存知己,天涯若比邻,喜欢就关注吧

把策略模式应用到实际项目中

喜欢就点击“好看”吧


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

500 Lines or Less

500 Lines or Less

Amy Brown、Michael DiBernardo / 2016-6-28 / USD 35.00

This book provides you with the chance to study how 26 experienced programmers think when they are building something new. The programs you will read about in this book were all written from scratch t......一起来看看 《500 Lines or Less》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具