日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Spring 環境下實現策略模式的示例

瀏覽:163日期:2023-08-09 10:10:15

背景

最近在忙一個需求,大致就是給滿足特定條件的用戶發營銷郵件,但是用戶的來源有很多方式:從 ES 查詢的、從 csv 導入的、從 MongoDB 查詢….. 需求很簡單,但是怎么寫的優雅,方便后續擴展,就存在很多門道了。

我們的項目是基于 Spring Boot 開發的,因此這篇文章也會基于 Spring Boot 作為基礎框架,教你如何使用 Spring 依賴注入的特性,優雅的實現策略模式。

1. 簡單粗暴

最簡單粗暴直接的方式莫過于 if...else… 了,偽代碼如下:

if(來源 == ES){ // TODO: ES Query}else if(來源 == CSV){ // TODO: Read CSV File}else if(來源 == MongoDB){ // TODO: MongoDB Query}

如果后面還需要從其他平臺獲取,那就在接著添加 else if...,這種方式固然簡單直接,但是當后續擴展的方式越來越多,相應的if...else...也會越來越長,emmm….. 怎么說呢,黑貓白貓,能抓到老鼠的就是好貓。

2. 策略模式

在 Spring 環境下實現策略模式異常簡單,畢竟 Spring 提供的依賴注入簡直就是開發利器~

既然是策略模式,那么定義策略肯定是首當其沖,策略我們使用枚舉實現最佳。

public enum GroupType { /** * 從 ES 查詢 */ ES, /** * 從 MongoDB 查詢 */ MONGODB, /** * 從 文件 讀取 */ FILE}

下一步,我們定義一個接口,用于抽象通用的功能。

public interface IGroupSelect { /** * 人群獲取方式 * * @return 人群選擇枚舉 */ GroupType type(); /** * 查詢滿足條件的用戶 * * @param groupQuery 查詢條件 * @return 滿足條件的用戶 */ default List<GroupUser> queryUser(GroupQuery groupQuery) { checkQueryCondition(groupQuery); return doQuery(groupQuery); } /** * 事前校驗查詢條件 * * @param groupQuery 查詢條件 * @throws IllegalArgumentException 參數異常 */ void checkQueryCondition(GroupQuery groupQuery) throws IllegalArgumentException; /** * 真正的查詢方法 * * @param groupQuery 查詢條件 * @return 滿足條件的用戶 */ List<GroupUser> doQuery(GroupQuery groupQuery);}

這一步,小伙伴們有沒有發現里面也包含了模板方法模式呢?

然后就是不同策略的具體實現了。

ES 策略

@Slf4j@Servicepublic class EsGroupSelect implements IGroupSelect { /** * 人群獲取方式 * * @return 人群選擇枚舉 */ @Override public GroupType type() { return GroupType.ES; } /** * 事前校驗查詢條件 * * @param groupQuery 查詢條件 * @throws IllegalArgumentException 參數異常 */ @Override public void checkQueryCondition(GroupQuery groupQuery) throws IllegalArgumentException { log.info('groupQuery = {}', groupQuery); } /** * 查詢滿足條件的用戶 * * @param groupQuery 查詢條件 * @return 滿足條件的用戶 */ @Override public List<GroupUser> doQuery(GroupQuery groupQuery) { List<GroupUser> result = new ArrayList<>(); // TODO: // 1. 復雜的 ES 查詢邏輯 // 2. 根據條件篩選滿足條件的用戶數據 for (int i = 1; i <= 15; i++) { result.add(GroupUser.of('ES用戶' + i, i + '@es.com')); } return result; }} 文件策略

@Slf4j@Servicepublic class FileGroupSelect implements IGroupSelect { /** * 人群獲取方式 * * @return 人群選擇枚舉 */ @Override public GroupType type() { return GroupType.FILE; } /** * 事前校驗查詢條件 * * @param groupQuery 查詢條件 * @throws IllegalArgumentException 參數異常 */ @Override public void checkQueryCondition(GroupQuery groupQuery) throws IllegalArgumentException { log.info('groupQuery = {}', groupQuery); } /** * 查詢滿足條件的用戶 * * @param groupQuery 查詢條件 * @return 滿足條件的用戶 */ @Override public List<GroupUser> doQuery(GroupQuery groupQuery) { List<GroupUser> result = new ArrayList<>(); // TODO: // 1. 復雜的解析、讀文件 // 2. 根據條件篩選滿足條件的用戶數據 for (int i = 1; i <= 3; i++) { result.add(GroupUser.of('文件讀取用戶' + i, i + '@file.com')); } return result; }} MongoDB 策略

@Slf4j@Servicepublic class MongoGroupSelect implements IGroupSelect { /** * 人群獲取方式 * * @return 人群選擇枚舉 */ @Override public GroupType type() { return GroupType.MONGODB; } /** * 事前校驗查詢條件 * * @param groupQuery 查詢條件 * @throws IllegalArgumentException 參數異常 */ @Override public void checkQueryCondition(GroupQuery groupQuery) throws IllegalArgumentException { log.info('groupQuery = {}', groupQuery); } /** * 查詢滿足條件的用戶 * * @param groupQuery 查詢條件 * @return 滿足條件的用戶 */ @Override public List<GroupUser> doQuery(GroupQuery groupQuery) { List<GroupUser> result = new ArrayList<>(); // TODO: // 1. 復雜的 MongoDB 查詢邏輯 // 2. 根據條件篩選滿足條件的用戶數據 for (int i = 1; i <= 7; i++) { result.add(GroupUser.of('MongoDB用戶' + i, i + '@mongo.com')); } return result; }}

現在到了最后一步,就是如何通過 Spring 優雅的實現策略模式的選擇呢?敲黑板,考試必考!

我們通過定義一個工廠類,然后使用 Spring 的依賴注入特性,可以注入一個接口的多個實現,這里采用 List<IGroupSelect> 的形式注入,Spring 也支持通過 Map<String,IGroupSelect> 的形式注入,如果使用 Map 注入,那么 key 就是類名,小伙伴們自己也可以測試一下~

@Servicepublic class GroupSelectFactory { @Autowired private List<IGroupSelect> groupSelectList; /** * 根據人群類型選擇具體的實現類 * * @param type 人群類型 * @return 人群選擇具體實現類 */ public IGroupSelect getGroupSelect(GroupType type) { Optional<IGroupSelect> groupSelectOptional = groupSelectList.stream().filter(t -> t.type() == type).findAny(); return groupSelectOptional.orElseThrow(() -> new IllegalArgumentException('暫不支持該人群方式')); }}

最后寫個定時任務測試一下吧。

@Autowiredprivate GroupSelectFactory groupSelectFactory;/** * 模擬定時發送營銷郵件 */@Scheduled(cron = '0/10 * * * * ?')public void sendEmailTask() { List<SendEmailTask> taskList = new ArrayList<>(); for (GroupType groupType : GroupType.values()) { GroupQuery groupQuery = new GroupQuery('虛頭巴腦的 ' + groupType.name() + ' 查詢條件'); taskList.add(SendEmailTask.of(groupType, groupQuery)); } taskList.forEach(task -> { List<GroupUser> groupUsers = groupSelectFactory.getGroupSelect(task.getType()).queryUser(task.getQuery()); log.info('groupUsers = {}', groupUsers); });}@Data@NoArgsConstructor@AllArgsConstructor(staticName = 'of')static class SendEmailTask implements Serializable { private static final long serialVersionUID = -3461263089669779193L; private GroupType type; private GroupQuery query;}

觀察控制臺,看看日志輸出吧~

總結

本文使用策略模式實現不同人群的查詢,后續如果要增加短信、微信、釘釘的消息發送,是不是也可以用策略模式實現呢? 使用 Spring 的依賴注入特性,可以注入一個接口的多個實現,很容易就實現了策略模式的選擇,這樣后續添加一種策略的時候,完全不需要改動主要邏輯,只需添加具體實現即可。 細心的小伙伴可以發現,本文雖然是講策略模式,其實里面還包含了模板方法、工廠模式,多種設計模式的協同作戰,食用味道更佳喲~

配套代碼:https://github.com/xkcoding/practice_demo/tree/master/strategy-design-pattern-in-spring

以上就是Spring 環境下實現策略模式的示例的詳細內容,更多關于Spring 實現策略模式的資料請關注好吧啦網其它相關文章!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
夜鲁夜鲁夜鲁视频在线播放| 日韩欧美国产精品综合嫩v| 欧美精品1区| 免费一级欧美片在线观看网站| 免费日韩成人| 久久久久久免费视频| 国产手机视频一区二区 | 老色鬼久久亚洲一区二区| 国产亚洲一区二区三区啪| 精品一区视频| 蜜臀久久99精品久久久久宅男| 青青草91视频| 91精品推荐| 热久久久久久| 黄色日韩在线| 麻豆久久一区| 久久国产精品亚洲77777| 欧美视频久久| 欧美理论视频| 国产精品1区在线| 蜜臀91精品国产高清在线观看| 日本在线成人| 激情欧美一区二区三区| 国产伦一区二区三区| 久久国产免费| 国产乱人伦精品一区| 亚洲成人精选| 国产精品不卡| 国产精品视频一区二区三区综合 | 精品视频黄色| 日韩中文字幕区一区有砖一区| bbw在线视频| 免费在线观看视频一区| 日韩一二三区在线观看| 桃色av一区二区| 国产无遮挡裸体免费久久| 奇米狠狠一区二区三区| 日韩精品一区二区三区av| 美国欧美日韩国产在线播放| 在线亚洲一区| 日本大胆欧美人术艺术动态| 视频一区视频二区中文字幕| 视频一区二区不卡| 亚洲欧洲美洲国产香蕉| 日韩欧美高清一区二区三区| 亚洲精品系列| 国产精品videosex极品| 国产一区二区三区精品在线观看| 成人精品久久| 精品国产三区在线| 中文一区一区三区免费在线观| 黑丝一区二区三区| 国产综合亚洲精品一区二| 午夜av成人| 欧美高清一区| 狠狠爱www人成狠狠爱综合网| 在线一区电影| 亚洲综合丁香| 日精品一区二区三区| 亚洲精品在线国产| 奇米亚洲欧美| 国产精品xxx| 狂野欧美性猛交xxxx| 国产精品亚洲欧美日韩一区在线| 18国产精品| 日本免费一区二区视频| 国产精品欧美一区二区三区不卡| 免费在线播放第一区高清av| 国产成人精品福利| 国产白浆在线免费观看| 欧美性感美女一区二区| 视频一区视频二区中文| 欧美一区激情| 国产91在线精品| 亚洲特级毛片| 蜜桃av一区二区三区电影| 国产精品久久久久久久久久妞妞| 精品久久久亚洲| 国产91精品对白在线播放| 亚洲欧美日韩国产一区| 亚洲bt欧美bt精品777| 精品资源在线| 国产亚洲精品久久久久婷婷瑜伽| 欧美日韩18| 免费精品国产| 国产精品扒开腿做爽爽爽软件| 久久激情网站| 国产精品免费精品自在线观看| 久久久久国产一区二区| 欧美视频二区| 国产视频一区三区| av资源中文在线| 日本一区二区三区视频在线看| 精品亚洲二区| 婷婷综合福利| 香蕉久久精品| 久久99国产精品视频| 久久99伊人| 日韩和的一区二在线| 国产精品一区2区3区| 亚洲欧美一级| 亚洲午夜91| 日本欧美不卡| 久久一区欧美| 国产精品17p| 亚洲ab电影| 热久久久久久久| 欧美日韩精品一本二本三本| 91看片一区| 日本一区二区免费高清| 偷拍亚洲精品| 亚洲欧洲国产精品一区| 久久国产精品99国产| 午夜久久99| 亚洲尤物在线| 亚洲欧美不卡| 国产视频欧美| 欧美专区在线| 视频精品一区| 日本亚洲最大的色成网站www| 久久亚洲视频| 亚洲日本欧美| 久久国产乱子精品免费女| 中文字幕中文字幕精品| 综合激情在线| 蜜桃av一区二区在线观看| 婷婷五月色综合香五月| 欧美偷窥清纯综合图区| 国产伦一区二区三区| 国产精品多人| 国产精品欧美在线观看| 加勒比视频一区| 精品视频国产| 亚洲播播91| 免费av一区| 日本不卡高清| 牛牛精品成人免费视频| 麻豆精品在线视频| 日韩伦理一区| 免费在线小视频| 亚洲成a人片| 亚洲高清av| 久久成人国产| 91精品蜜臀一区二区三区在线 | 亚洲一二三区视频| 欧美一区在线观看视频| 日韩视频二区| 亚洲人成精品久久久| 国产欧美一级| 日韩精品欧美| 日韩欧美激情| 天堂√8在线中文| 美女少妇全过程你懂的久久| 亚洲欧洲专区| 亚洲爱爱视频| 97精品久久| 亚洲爱爱视频| 婷婷综合国产| 欧美日韩一二三四| 日韩av一区二区三区四区| 中文字幕人成乱码在线观看| 在线视频亚洲欧美中文| 国产成年精品| 在线精品亚洲| se01亚洲视频 | 蜜臀av免费一区二区三区| 日本成人手机在线| 99久久久久| 久久99久久人婷婷精品综合| 在线成人直播| 日韩专区精品| 日本电影久久久| 99久久婷婷这里只有精品| 日本视频在线一区| 黄色成人91| 久久久人人人| 美女高潮久久久| 婷婷综合一区| 免费人成在线不卡| 国内精品伊人| 国产亚洲精品美女久久| 免费成人在线观看| 99久久激情| 日韩久久一区二区三区| 欧美国产极品| 国产欧美一级| 久久黄色影视| 日韩激情网站| 一区二区三区午夜视频| 先锋影音国产一区| 亚洲一级特黄| 免费av一区二区三区四区| 高清日韩欧美| 成人精品国产亚洲| 国产精品一区二区精品视频观看 | 一区二区三区四区在线观看国产日韩| 在线日韩一区| 99视频精品全部免费在线视频| 日韩精品dvd| 久久久久91|