策略模式经典应用,函数式接口策略模式,枚举策略模式

本文详细介绍了策略模式的原理,包括定义、创建和使用。提到了经典的应用场景,如根据配置或用户输入动态指定策略。同时,讨论了如何通过函数式接口和枚举来实现策略模式,强调了策略模式的灵活性,使得算法变化不会影响到客户端。总结指出,策略模式有助于遵循开闭原则,降低引入错误的风险,并提示在条件适合时才考虑使用该模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

策略模式

原理

Strategy Design Pattern 策略模式

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

定义一族算法类,将每个算法分别封装起来,让它们可以互相替换

策略模式实际上是解耦策略的定义、创建、使用

  1. 策略的定义指的是策略类和策略接口,策略模式的骨架
  2. 策略的创建指的是通过工厂类或工厂的工厂将策略的创建和使用通过查表法关联到一起
  3. 策略的使用在业务逻辑中通过工厂类获取策略的运行时状态并执行,运行时可根据配置或用户输入动态指定

经典应用

分创建,定义,使用,每次拓展需要新增策略类和修改工厂类,利用反射可以实现扩展开放对修改关闭。

代码

// 定义
public interface Strategy {
    void algorithmInterface();
}
public class ConcreteStrategyA implements Strategy {
    @Override
    public void algorithmInterface() {
        //具体的算法...
    }
}
public class ConcreteStrategyB implements Strategy {
    @Override
    public void algorithmInterface() {
        //具体的算法...
    }
}

// 创建
public class StrategyFactory {
    private static final Map<String, Strategy> strategies = new HashMap<>();
    static {
        strategies.put("A", new ConcreteStrategyA());
        strategies.put("B", new ConcreteStrategyB());
    }
    // 根据 type 获取策略类
    public static Strategy getStrategy(String type) {
        if (type == null || type.isEmpty()) {
            throw new IllegalArgumentException("type should not be empty.");
        }
        return strategies.get(type);
    }
}

// 使用
// 运行时动态确定,根据配置文件的配置决定使用哪种策略
    public static void main(String[] args) throws Exception {
        Strategy strategy = null;
        Properties props = new Properties();
        props.load(new FileInputStream("./config.properties"));
        String type = props.getProperty("eviction_type");
        strategy = StrategyFactory.getStrategy(type);
        strategy.algorithmInterface();
        //...
    }

// 非运行时动态确定,在代码中指定使用哪种策略
    public static void main(String[] args) {
        //...
        Strategy strategy = new ConcreteStrategyA();
        strategy.algorithmInterface();
        //...
    }

函数式接口和枚举策略模式

策略模式的简单应用场景:

  • map + 函数接口实现,新增策略类则新增方法修改 map
// 接口用于暴露调用方法
public interface TaskCenterService {
    Boolean sendFunction(Integer id, TaskSendRewardDto taskSendRewardDto);
}
// 实现类
@Service
public class TaskCenterServiceImpl implements TaskCenterService {
    private Map<Integer, Function<TaskSendRewardDto,Boolean>> sendGiftFunction = new HashMap<>(); ;
    public TaskCenterServiceImpl(){
        //0银币/1金币/2礼物/3道具
        sendGiftFunction.put(0,this::sendSilver);
        sendGiftFunction.put(1,this::sendGold);
        sendGiftFunction.put(2,this::sendGift);
        sendGiftFunction.put(3,this::sendDepProp);
    }
    private Boolean sendSilver(TaskSendRewardDto taskSendRewardDto){
        return true;
    }
    private Boolean sendGold(TaskSendRewardDto taskSendRewardDto){
        return true;
    }
    private Boolean sendGift(TaskSendRewardDto taskSendRewardDto){
        return true;
    }
    private Boolean sendDepProp(TaskSendRewardDto taskSendRewardDto){
        return true;
    }
    @Override
    public Boolean sendFunction(Integer id, TaskSendRewardDto taskSendRewardDto) {
        return sendGiftFunction.get(id).apply(taskSendRewardDto);
    }
}
// 使用
@RequiredArgsConstructor
@Component
@Slf4j
public class DepPropAward implements IAwardDistribute {

    @NonNull
    private TaskCenterService taskCenterService;

    @Override
    public void distribute(AwardInfo awardInfo) throws AwardDistributeException {
        TaskSendRewardDto dto = new TaskSendRewardDto();
        try {
            BeanUtils.copyProperties(dto, awardInfo);
        } catch (IllegalAccessException | InvocationTargetException e) {
            log.error("DepPropAward-copyProperties-error:", e);
            throw new AwardDistributeException(e);
        }
        taskCenterService.sendFunction(3, dto);
    }
}
  • 枚举策略模式,新增策略则新增枚举子类
public enum JumpRuleEnum {
    INDEX_PAGE("首页", 1) {
        @Override
        public String backUrl(JumpParamDto dto) {
            return null;
        }
    },
    STICKER_DETAILS_PAGE("贴纸详情", 28) {
        @Override
        public String backUrl(JumpParamDto dto) {
            return null;
        }
    },
    HEAD_SCULPTURE_PAGE("头像框", 29) {
        @Override
        public String backUrl(JumpParamDto dto) {
            return null;
        }
    },
    SYSTEM_PAGE("系统消息", 98) {
        @Override
        public String backUrl(JumpParamDto dto) {
            return null;
        }
    };

    private String msg;
    private Integer type;

    public static JumpParamEnum genJumpEnum(String name) {
        return JumpRuleEnum.valueOf(name);
    }

    JumpRuleEnum(String msg, Integer type) {
        this.msg = msg;
        this.type = type;
    }
    /**
     * 抽象方法 枚举策略子类必须实现
     */
    public abstract String backUrl(JumpParamDto dto);
}

// 使用
String url = JumpRuleEnum.genJumpEnum(name).backUrl(dto);

总结

  • 策略模式定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端
  • 策略模式用来解耦策略的定义、创建、使用。实际上,一个完整的策略模式就是由这三个部分组成的
  • 策略模式满足开闭原则添加新策略的时候,最小化、集中化代码改动,减少引入 bug 的风险
  • 如果 if-else 分支判断不复杂、代码不多就不要过度设计使用策略模式,遵循 KISS 原则
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值