java三层架构是不是策略模式,把「策略模式」应用到实际项目中
無論你知不知道這個設(shè)計模式,但必定在項目中都似曾相識。倘若僅僅聊理論必然枯燥乏味,只有理論和實戰(zhàn)相結(jié)合方可達(dá)到人劍合一的境界。
首先,我來說個需求,倘若是你遇到該如何做?你可停留幾分鐘,想出你的解決方式,可在下方留言,說出你的想法。
需求
用戶有文件上傳的需求,而我們要負(fù)責(zé)對文件進(jìn)行存儲,由于我們的系統(tǒng)可能會單獨給個別客戶私有化部署(部署盡量少依賴中間件能服務(wù)等),同時我們也會自己運營成為自己的SaaS服務(wù)(保證服務(wù)的高可用等)。
所以我們有兩點需求:
要在SaaS版本中將文件存入分布式存儲系統(tǒng)fastDfs中
客戶的私有部署中將文件?存儲在數(shù)據(jù)庫中
思路
尋找異同點
文件上傳過程這個無論什么版本部署都是一樣的,所以暫不考慮。
文件存儲的方式不同,同時文件的獲取和刪除也不同
保存,獲取,刪除后的響應(yīng)也是相同的,也不考慮了。
開始抽象
當(dāng)前我們考慮的就是文件的存儲,獲取和刪除了。同樣的行為,不同的實現(xiàn),我們必定想到定義一個接口:
/**
* 文件存儲接口
* Identify表示文件的唯一標(biāo)識,可任意類型
* T 表示 上傳下載的返回類型,可任意類型
*
* @author flyhero
* @date 2019-02-01 11:18 AM
*/
public interface IStorageService {
/**
* 上傳文件
*
* @param file
* @return
*/
T upload(MultipartFile file);
/**
* 下載文件
*
* @param identify
* @return
*/
T download(Identify identify);
/**
* 刪除文件
*
* @param identify
*/
void delete(Identify identify);
}
兩種不同的實現(xiàn)
存儲FastDfs
@Slfj
@Service("fastDfsServiceImpl")
public class FastDfsServiceImpl implements IStorageService {
@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刪除文件");
}
}
存儲 數(shù)據(jù)庫
@Slfj
@Service("databaseServiceImpl")
public class DatabaseServiceImpl implements IStorageService {
@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刪除文件");
}
}
調(diào)用
@Service
public class FileServiceImpl implements FileService {
// 同一個接口根據(jù)不同的名稱調(diào)用不同的實現(xiàn)
// @Qualifier("databaseServiceImpl")
@Qualifier("fastDfsServiceImpl")
@Autowired
private IStorageService storageService;
public void save(MultipartFile file){
if (null == file) {
throws new Exception("文件不能為空");
}
FileVo fileVo = storageService.upload(file);
}
}
疑惑
可能有人會說了:這怎么和我了解的策略模式不一樣啊,策略模式不是這樣的嗎?
你說的對!但這是在沒有任何框架下的設(shè)計模式,而我們現(xiàn)在普遍使用的都是Spring框架,那么標(biāo)準(zhǔn)的策略模式中的Context去哪里了?
引入Context的作用
首先我們要知道引入Context的作用,是為了避免高層直接與策略接口直接交互,為什么呢?因為我們策略模式接口功能相對比較單一,而有些高層模塊可能需要一些比較復(fù)雜的交互。
若直接調(diào)用接口,則需要對每個實現(xiàn)增加邏輯;
若直接調(diào)用前,執(zhí)行增強邏輯,那么多個地方使用時,會存在重復(fù)增強邏輯,并可能忘掉。
此時引入Context是解決問題的最佳方式。
而我們的FileServiceImpl就相當(dāng)于Context的作用,由于我們使用Spring框架且使用了三層架構(gòu),暴露上傳文件、下載文件、刪除文件是在controller層三個不同的方法中(或不同的controller中),為了避免幾個地方使用的存儲策略不同,我直接在Context中來指定使用的策略,當(dāng)需要切換時也非常方便,只需要更改IStorageService的注解即可。
總結(jié)
優(yōu)點
策略實現(xiàn)類可自由切換
易于擴展,若還有新的策略只要新增策略接口一個實現(xiàn)類即可
不必使用條件語句進(jìn)行決定使用哪個策略
缺點
策略類一旦增多,調(diào)用者要清楚的知道各種策略的區(qū)別
如果你有不同的看法,還望不吝指教。
更多精彩技術(shù)文章盡在微信公眾號:碼上實戰(zhàn)
總結(jié)
以上是生活随笔為你收集整理的java三层架构是不是策略模式,把「策略模式」应用到实际项目中的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php统计变量的位数,php实现统计二进
- 下一篇: oracle的监听器是什么,Oracle