在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

為什么我不再推薦枚舉策略模式?

jf_ro2CN3Fa ? 來源:芋道源碼 ? 2023-04-14 10:52 ? 次閱讀


一、為什么講策略模式

策略模式,應該是工作中比較常用的設計模式,調用方自己選擇用哪一種策略完成對數據的操作,也就是“一個類的行為或其算法可以在運行時更改”

我個人的理解是 將一些除了過程不同其他都一樣的函數封裝成策略,然后調用方自己去選擇想讓數據執行什么過程策略。常見的例子為根據用戶分類推薦不同的排行榜(用戶關注點不一樣,推薦榜單就不一樣)

和單例模式一樣,隨著時間發展,我不再推薦經典策略模式,更推薦簡單策略用枚舉策略模式,復雜地用工廠策略模式。下面引入一個例子,我們的需求是:對一份股票數據列表,給出低價榜、高價榜、漲幅榜。這其中只有排序條件的區別,比較適合作為策略模式的例子

基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

  • 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 視頻教程:https://doc.iocoder.cn/video/

二、經典策略模式

數據DTO

@Data
publicclassStock{

//股票交易代碼
privateStringcode;

//現價
privateDoubleprice;

//漲幅
privateDoublerise;
}

抽象得到的策略接口

publicinterfaceStrategy{

/**
*將股票列表排序
*
*@paramsource源數據
*@return排序后的榜單
*/
Listsort(Listsource);
}

實現我們的策略類

/**
*高價榜
*/
publicclassHighPriceRankimplementsStrategy{

@Override
publicListsort(Listsource){
returnsource.stream()
.sorted(Comparator.comparing(Stock::getPrice).reversed())
.collect(Collectors.toList());
}
}

/**
*低價榜
*/
publicclassLowPriceRankimplementsStrategy{

@Override
publicListsort(Listsource){
returnsource.stream()
.sorted(Comparator.comparing(Stock::getPrice))
.collect(Collectors.toList());
}
}

/**
*高漲幅榜
*/
publicclassHighRiseRankimplementsStrategy{

@Override
publicListsort(Listsource){
returnsource.stream()
.sorted(Comparator.comparing(Stock::getRise).reversed())
.collect(Collectors.toList());
}
}

經典的Context類,

publicclassContext{
privateStrategystrategy;

publicvoidsetStrategy(Strategystrategy){
this.strategy=strategy;
}

publicListgetRank(Listsource){
returnstrategy.sort(source);
}
}

于是 我們順禮成章地得到調用類--榜單實例RankServiceImpl

@Service
publicclassRankServiceImpl{

/**
*dataService.getSource()提供原始的股票數據
*/
@Resource
privateDataServicedataService;

/**
*前端傳入榜單類型,返回排序完的榜單
*
*@paramrankType榜單類型
*@return榜單數據
*/
publicListgetRank(StringrankType){
//創建上下文
Contextcontext=newContext();
//這里選擇策略
switch(rankType){
case"HighPrice":
context.setStrategy(newHighPriceRank());
break;
case"LowPrice":
context.setStrategy(newLowPriceRank());
break;
case"HighRise":
context.setStrategy(newHighRiseRank());
break;
default:
thrownewIllegalArgumentException("rankTypenotfound");
}
//然后執行策略
returncontext.getRank(dataService.getSource());
}
}

我們可以看到經典方法,創建了一個接口、三個策略類,還是比較啰嗦的。調用類的實現也待商榷,新增一個策略類還要修改榜單實例(可以用抽象工廠解決,但是復雜度又上升了)。加之我們有更好的選擇,所以此處不再推薦經典策略模式

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

  • 項目地址:https://github.com/YunaiV/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn/video/

三、基于枚舉的策略模式

這里對這種簡單的策略,推薦用枚舉進行優化。枚舉的本質是創建了一些靜態類的集合。

我下面直接給出例子,大家可以直觀感受一下

枚舉策略類

publicenumRankEnum{
//以下三個為策略實例
HighPrice{
@Override
publicListsort(Listsource){
returnsource.stream()
.sorted(Comparator.comparing(Stock::getPrice).reversed())
.collect(Collectors.toList());
}
},
LowPrice{
@Override
publicListsort(Listsource){
returnsource.stream()
.sorted(Comparator.comparing(Stock::getPrice))
.collect(Collectors.toList());
}
},
HighRise{
@Override
publicListsort(Listsource){
returnsource.stream()
.sorted(Comparator.comparing(Stock::getRise).reversed())
.collect(Collectors.toList());
}
};

//這里定義了策略接口
publicabstractListsort(Listsource);
}

對應的調用類也得以優化,榜單實例RankServiceImpl

@Service
publicclassRankServiceImpl{

/**
*dataService.getSource()提供原始的股票數據
*/
@Resource
privateDataServicedataService;

/**
*前端傳入榜單類型,返回排序完的榜單
*
*@paramrankType榜單類型形似RankEnum.HighPrice.name()
*@return榜單數據
*/
publicListgetRank(StringrankType){
//獲取策略,這里如果未匹配會拋IllegalArgumentException異常
RankEnumrank=RankEnum.valueOf(rankType);
//然后執行策略
returnrank.sort(dataService.getSource());
}
}

可以看到,如果策略簡單的話,基于枚舉的策略模式優雅許多,調用方也做到了0修改,但正確地使用枚舉策略模式需要額外考慮以下幾點。

  • 枚舉的策略類是公用且靜態,這意味著這個策略過程不能引入非靜態的部分,擴展性受限
  • 策略模式的目標之一,是優秀的擴展性和可維護性,最好能新增或修改某一策略類時,對其他類是無改動的。而枚舉策略如果過多或者過程復雜,維護是比較困難的,可維護性受限

四、基于工廠的策略模式

為了解決良好的擴展性和可維護性,我更推薦以下利用spring自帶beanFactory的優勢,實現一個基于工廠的策略模式。

策略類改動只是添加了@Service注解,并指定了Service的value屬性

/**
*高價榜
*注意申明Service.value=HighPrice,他是我們的key,下同
*/
@Service("HighPrice")
publicclassHighPriceRankimplementsStrategy{

@Override
publicListsort(Listsource){
returnsource.stream()
.sorted(Comparator.comparing(Stock::getPrice).reversed())
.collect(Collectors.toList());
}
}

/**
*低價榜
*/
@Service("LowPrice")
publicclassLowPriceRankimplementsStrategy{

@Override
publicListsort(Listsource){
returnsource.stream()
.sorted(Comparator.comparing(Stock::getPrice))
.collect(Collectors.toList());
}
}

/**
*高漲幅榜
*/
@Service("HighRise")
publicclassHighRiseRankimplementsStrategy{

@Override
publicListsort(Listsource){
returnsource.stream()
.sorted(Comparator.comparing(Stock::getRise).reversed())
.collect(Collectors.toList());
}
}

調用類修改較大,接入借助spring工廠特性,完成策略類

@Service
publicclassRankServiceImpl{

/**
*dataService.getSource()提供原始的股票數據
*/
@Resource
privateDataServicedataService;
/**
*利用注解@Resource@Autowired特性,直接獲取所有策略類
*key=@Service的value
*/
@Resource
privateMaprankMap;

/**
*前端傳入榜單類型,返回排序完的榜單
*
*@paramrankType榜單類型和Service注解的value屬性一致
*@return榜單數據
*/
publicListgetRank(StringrankType){
//判斷策略是否存在
if(!rankMap.containsKey(rankType)){
thrownewIllegalArgumentException("rankTypenotfound");
}
//獲得策略實例
Strategyrank=rankMap.get(rankType);
//執行策略
returnrank.sort(dataService.getSource());
}
}

若讀者使用的不是Spring,也可以找找對應框架的工廠模式實現,或者自己實現一個抽象工廠。

工廠策略模式會比枚舉策略模式啰嗦,但也更加靈活、易擴展性和易維護。故簡單策略推薦枚舉策略模式,復雜策略才推薦工廠策略模式。



審核編輯 :李倩



聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 框架
    +關注

    關注

    0

    文章

    403

    瀏覽量

    17543
  • 函數
    +關注

    關注

    3

    文章

    4346

    瀏覽量

    62974

原文標題:為什么我不再推薦枚舉策略模式?

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    設計模式-策略模式

    作者:京東工業 孫磊 一、概念 策略模式(Strategy Pattern)也稱為(Policy Parttern)。 它定義了算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變換
    的頭像 發表于 01-08 13:47 ?102次閱讀
    設計<b class='flag-5'>模式</b>-<b class='flag-5'>策略</b><b class='flag-5'>模式</b>

    Java 枚舉策略模式、函數式接口的結合:實現高內聚低耦合的設計

    中,通常會使用枚舉來定義業務上的一組常量,那除了簡單地定義常量之外,我們如何利用枚舉來實現高內聚、低耦合的設計呢?下面介紹下枚舉策略模式
    的頭像 發表于 11-21 14:06 ?289次閱讀

    請問什么情況下會損壞TLV2548,或者導致INT信號不再反應?

    如題,請問什么情況下會損壞TLV2548,或者導致INT信號不再反應? 曾多次驅動過該AD,都可以正常讀取碼值。但有兩次遇到過AD沒有任何反應,只在上電的瞬間讀取電壓,INT不再拉低(
    發表于 11-14 06:39

    蘋果調整策略:逐步摒棄年更產品發布模式

    10月8日訊,彭博社知名記者馬克·古爾曼在《Power On》通訊中揭示,蘋果公司正逐步轉變其傳統的“年度更新”發布模式,邁向更為靈活的產品發布策略
    的頭像 發表于 10-08 16:46 ?844次閱讀

    stm32f407 USB外接HUB怎么枚舉HUB和其他USB設備?

    stm32f407 的USB接口 想外接一個HUB 來支持更多的USB設備,但是這個HUB 該怎么枚舉,還有就是HUB下的USB設備怎么枚舉,有做過的大神嗎。求指導,求demo。小弟拜謝了
    發表于 04-29 08:13

    STM32F103 USB枚舉不成功的原因?

    (NVIC_VectTab_FLASH,0x8800),但此時USB便枚舉不成功,此時其他中斷是正常的;但若把APP起始地址改為0X8000000不使用IAP進行跳轉則枚舉沒有問題.比較懷疑中斷向量這塊的設置是不是還有問題,跪
    發表于 04-29 06:29

    stm32f103 usb枚舉問題求解

    移植了一個USB HID設備,發現必須初始化usart1,這樣usb hid設備才能枚舉,否則枚舉失敗,沒有發現硬件上有聯系啊?
    發表于 04-26 07:57

    調試USB hots的時候,枚舉過不去,為什么?

    調試USB hots的時候,枚舉過不去,第一步的狀態都不對。看數據是中斷函數USBH_OTG_ISR_Handler返回的,請問哪位有相關說明發一下,現在總是觸發gintsts.b.sofintr中斷。謝謝!
    發表于 04-10 07:28

    CYUS3014 RAM燒寫成功,為什么枚舉不起來?

    CYUSB3014 RAM顯示燒寫成功后,缺不再枚舉,技術支持讓更換芯片后,問題依舊,請問是否還有別的方式可以查找問題?
    發表于 02-29 07:13

    cyusb3014枚舉的工作原理是什么?如果下載固件后不枚舉,可能會是什么原因,原理是什么?

    用3014設計自己的板子,參考開發板kit3的原理圖,插入計算機后可以被識別為Bootloader,采用USB啟動模式,下載實例中的固件后,顯示燒寫成功,但設備在計算機中消失了,不再重新被
    發表于 02-29 07:11

    通常情況下CYUSB3014枚舉后的結果都會顯示為Bootloader,如何改變枚舉結果?

    通常情況下CYUSB3014枚舉后的結果都會顯示為Bootloader 如果向讓USB3.0連接以后,將我連接的設備識別成ChinaBeijing .請問我應該如何操作??
    發表于 02-28 08:01

    如何同時枚舉SlaveFIFO和UART(CDC)?

    使用Re: Slave FIFO + UART Driver Setup中的程序,將img下載進FX3中,成功枚舉出了“USB串行設備(COM13)”,但是并沒有出現
    發表于 02-28 07:23

    如何在SlaveFifoSync例程中添加HID設備枚舉

    您好,使用了SlaveFifoSync的32bit模式例程,現在想在其中添加一個HID的設備(鼠標),程序見附件,參照了Can EZ-USB FX3 enumerate seri
    發表于 02-28 06:31

    cx3初始化GPIO會停止UVC枚舉的原因?

    需要使用 GPIO 為的圖像傳感器和其他設備進行重置控制。 為此,正在嘗試在的 CSI 生成的代碼中添加簡單的 GPIO 控制,但是當我添加以下幾行時,
    發表于 02-27 07:38

    cyusb3014進入DP替代模式后斷開USB連接是什么原因?

    使用USB3.0 + dp2lane mode),請問可能是什么原因嗎? 有兩個猜測: 1. 檢查 usb3.0+dp2lane 后是否會再次枚舉USB模式已協商。 枚舉失敗 2
    發表于 02-23 08:17
    主站蜘蛛池模板: 激情五月播播 | 国产在线干 | 久久69| 国产高清在线免费 | 午夜影院在线看 | 国产在线一卡二卡 | 国产片无遮挡在线看床戏 | 黑色丝袜美女被视频网站 | 亚洲综合视频一区 | 福利视频一区二区微拍堂 | 日韩久久精品视频 | 特级做a爰片毛片免费看一区 | 四虎永久网址 | 中文字幕第8页 | 四虎影视在线观看 | 免费人成网ww777kkk手机 | 看全色黄大色大片免费久久 | xxx日本69hd | 日韩欧美视频在线一区二区 | 亚洲成a人片777777久久 | 国产午夜免费 | 欧美亚洲视频一区 | 亚洲五月综合缴情婷婷 | 亚洲第一中文字幕 | 久久www免费人成高清 | 特黄特黄特色大片免费观看 | 3344a毛片在线看 | 极品美女洗澡后露粉嫩木耳视频 | 精品一区二区三区视频 | 成在线人永久免费播放视频 | 国产女人视频免费观看 | 中文字幕卡二和卡三的视频 | 在线观看886影院成人影院 | 免费一级牲交毛片 | 午夜影院性 | 最新激情网 | 九九九精品 | 激情网五月 | 国产www色| 天天艹天天艹 | 国产毛片久久国产 |