![为什么我不再推荐枚举策略模式?](http://img.jiangsulong.com/220401/162PUC1-0.jpg)
文章插图
一、为什么讲策略模式策略模式,应该是工作中比较常用的设计模式,调用方自己选择用哪一种策略完成对数据的操作,也就是“一个类的行为或其算法可以在运行时更改”
我个人的理解是 将一些除了过程不同其他都一样的函数封装成策略,然后调用方自己去选择想让数据执行什么过程策略 。常见的例子为根据用户分类推荐不同的排行榜(用户关注点不一样,推荐榜单就不一样)
和单例模式一样,随着时间发展,我不再推荐经典策略模式,更推荐简单策略用枚举策略模式,复杂地用工厂策略模式 。下面引入一个例子,我们的需求是:对一份股票数据列表,给出低价榜、高价榜、涨幅榜 。这其中只有排序条件的区别,比较适合作为策略模式的例子
二、经典策略模式【为什么我不再推荐枚举策略模式?】数据DTO
@Datapublic class Stock {// 股票交易代码private String code;// 现价private Double price;// 涨幅private Double rise;}
抽象得到的策略接口public interface Strategy {/*** 将股票列表排序** @param source 源数据* @return 排序后的榜单*/List<Stock> sort(List<Stock> source);}
实现我们的策略类/** * 高价榜 */public class HighPriceRank implements Strategy {@Overridepublic List<Stock> sort(List<Stock> source) {return source.stream().sorted(Comparator.comparing(Stock::getPrice).reversed()).collect(Collectors.toList());}}/** * 低价榜 */public class LowPriceRank implements Strategy {@Overridepublic List<Stock> sort(List<Stock> source) {return source.stream().sorted(Comparator.comparing(Stock::getPrice)).collect(Collectors.toList());}}/** * 高涨幅榜 */public class HighRiseRank implements Strategy {@Overridepublic List<Stock> sort(List<Stock> source) {return source.stream().sorted(Comparator.comparing(Stock::getRise).reversed()).collect(Collectors.toList());}}
经典的Context类,public class Context {private Strategy strategy;public void setStrategy(Strategy strategy) {this.strategy = strategy;}public List<Stock> getRank(List<Stock> source) {return strategy.sort(source);}}
于是 我们顺礼成章地得到调用类--榜单实例RankServiceImpl@Servicepublic class RankServiceImpl {/*** dataService.getSource() 提供原始的股票数据*/@Resourceprivate DataService dataService;/*** 前端传入榜单类型, 返回排序完的榜单** @param rankType 榜单类型* @return 榜单数据*/public List<Stock> getRank(String rankType) {// 创建上下文Context context = new Context();// 这里选择策略switch (rankType) {case "HighPrice":context.setStrategy(new HighPriceRank());break;case "LowPrice":context.setStrategy(new LowPriceRank());break;case "HighRise":context.setStrategy(new HighRiseRank());break;default:throw new IllegalArgumentException("rankType not found");}// 然后执行策略return context.getRank(dataService.getSource());}}
我们可以看到经典方法,创建了一个接口、三个策略类,还是比较啰嗦的 。调用类的实现也待商榷,新增一个策略类还要修改榜单实例(可以用抽象工厂解决,但是复杂度又上升了) 。加之我们有更好的选择,所以此处不再推荐经典策略模式三、基于枚举的策略模式这里对这种简单的策略,推荐用枚举进行优化 。枚举的本质是创建了一些静态类的集合 。
我下面直接给出例子,大家可以直观感受一下
枚举策略类
public enum RankEnum {// 以下三个为策略实例HighPrice {@Overridepublic List<Stock> sort(List<Stock> source) {return source.stream().sorted(Comparator.comparing(Stock::getPrice).reversed()).collect(Collectors.toList());}},LowPrice {@Overridepublic List<Stock> sort(List<Stock> source) {return source.stream().sorted(Comparator.comparing(Stock::getPrice)).collect(Collectors.toList());}},HighRise {@Overridepublic List<Stock> sort(List<Stock> source) {return source.stream().sorted(Comparator.comparing(Stock::getRise).reversed()).collect(Collectors.toList());}};// 这里定义了策略接口public abstract List<Stock> sort(List<Stock> source);}
对应的调用类也得以优化,榜单实例RankServiceImpl@Servicepublic class RankServiceImpl {/*** dataService.getSource() 提供原始的股票数据*/@Resourceprivate DataService dataService;/*** 前端传入榜单类型, 返回排序完的榜单** @param rankType 榜单类型 形似 RankEnum.HighPrice.name()* @return 榜单数据*/public List<Stock> getRank(String rankType) {// 获取策略,这里如果未匹配会抛 IllegalArgumentException异常RankEnum rank = RankEnum.valueOf(rankType);// 然后执行策略return rank.sort(dataService.getSource());}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 夫妻关系变得越来越陌生 夫妻间越来越陌生语录
- 为什么毕业季会变成分手季 为什么毕业季是分手季
- 为什么说鲸鱼一生孤独,鲸落的寓意和象征有哪些
- 男朋友不馋我身子是什么情况,睡一起却不碰你的男人心理
- 什么人不适合喝苦荞茶
- 痛风不能吃哪些东西
- 长痘痘不能吃什么
- 大厨分享家常版地三鲜 家常地三鲜
- 韩国人口数量还不如我国浙江 韩国总面积有多大
- 农村不让建房子 农村为什么不允许建房