策略模式之枚举、工厂模式

本文探讨了使用枚举和基于工厂的策略模式在处理股票排序场景中的应用。枚举策略模式简洁但扩展性有限,而工厂模式通过Spring的beanFactory提供了更好的扩展性和可维护性。通过添加@Service注解并指定value属性,可以方便地创建和管理不同的排序策略。在实际应用中,可以根据需求选择合适的策略实现方式。
摘要由CSDN通过智能技术生成

基于枚举策略类

public enum RankEnum {
    // 以下三个为策略实例
    HighPrice {
        @Override
        public List<Stock> sort(List<Stock> source) {
            return source.stream()
                    .sorted(Comparator.comparing(Stock::getPrice).reversed())
                    .collect(Collectors.toList());
        }
    },
    LowPrice {
        @Override
        public List<Stock> sort(List<Stock> source) {
            return source.stream()
                    .sorted(Comparator.comparing(Stock::getPrice))
                    .collect(Collectors.toList());
        }
    },
    HighRise {
        @Override
        public 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

@Service
public class RankServiceImpl {

    /**
     * dataService.getSource() 提供原始的股票数据
     */
    @Resource
    private 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());
    }
}

基于枚举的策略模式优雅许多,调用方也做到了0修改,但正确地使用枚举策略模式需要额外考虑以下几点。

  • 枚举的策略类是公用且静态,这意味着这个策略过程不能引入非静态的部分,扩展性受限

  • 策略模式的目标之一,是优秀的扩展性和可维护性,最好能新增或修改某一策略类时,对其他类是无改动的。而枚举策略如果过多或者过程复杂,维护是比较困难的,可维护性受限

基于工厂的策略模式

为了解决良好的扩展性和可维护性,我更推荐以下利用spring自带beanFactory的优势,实现一个基于工厂的策略模式。    策略类改动只是添加了@Service注解,并指定了Service的value属性

/**
 * 高价榜
 * 注意申明 Service.value = HighPrice,他是我们的key,下同
 */
@Service("HighPrice")
public class HighPriceRank implements Strategy {

    @Override
    public List<Stock> sort(List<Stock> source) {
        return source.stream()
                .sorted(Comparator.comparing(Stock::getPrice).reversed())
                .collect(Collectors.toList());
    }
}

/**
 * 低价榜
 */
@Service("LowPrice")
public class LowPriceRank implements Strategy {

    @Override
    public List<Stock> sort(List<Stock> source) {
        return source.stream()
                .sorted(Comparator.comparing(Stock::getPrice))
                .collect(Collectors.toList());
    }
}

/**
 * 高涨幅榜
 */
@Service("HighRise")
public class HighRiseRank implements Strategy {

    @Override
    public List<Stock> sort(List<Stock> source) {
        return source.stream()
                .sorted(Comparator.comparing(Stock::getRise).reversed())
                .collect(Collectors.toList());
    }
}

调用类修改较大,接入借助spring工厂特性,完成策略类

@Service
public class RankServiceImpl {

    /**
     * dataService.getSource() 提供原始的股票数据
     */
    @Resource
    private DataService dataService;
    /**
     * 利用注解@Resource和@Autowired特性,直接获取所有策略类
     * key = @Service的value
     */
    @Resource
    private Map<String, Strategy> rankMap;

    /**
     * 前端传入榜单类型, 返回排序完的榜单
     *
     * @param rankType 榜单类型 和Service注解的value属性一致
     * @return 榜单数据
     */
    public List<Stock> getRank(String rankType) {
        // 判断策略是否存在
        if (!rankMap.containsKey(rankType)) {
            throw new IllegalArgumentException("rankType not found");
        }
        // 获得策略实例
        Strategy rank = rankMap.get(rankType);
        // 执行策略
        return rank.sort(dataService.getSource());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值