策略模式

概述

《设计模式》一书中对于 “策略模式” 的意图描述如下:

定义一系列算法,将它们一个个封装起来,并是他们可以相互替代

一般策略模式的 UML 图如下所示:

strategy_pattern_uml.png

一般在以下几种情况中使用策略模式:

  • 许多相关的类仅仅是行为有异。“策略” 提供了一种用多个行为中的一个行为来配置一个类的方法
  • 需要使用一个算法的不同变体。比如,在不同的使用场景下,可能需要考虑时间/空间复杂度较为优秀的算法
  • 算法使用了客户端不应该知道的数据
  • 一个类定义了多种行为,并且这些行为在这个类的操作中一多个条件语句的形式出现

具体示例

假设现在存在一个需要计算利息的的测算模型,对于不同的测算模型,需要采取不同的利息测算算法,一般常见的测算算法分为等额本金和等额本息,可能不同的资产管理公司还会存在其它的测算算法,为了能够可扩展地对利息进行测算,我们需要将利息的测算和当前的上下文进行分离,有具体的使用场景来决定采用何种测算算法

首先,我们定义我们的利息测算的接口策略 InterestCalStrategy

public interface InterestCalStrategy {
    /**
    	根据传入的本金信息计算对应的还本付息计划
    */
    List<CashFlow> calInterest(List<Principal> prinicipalList);
}

对于不同的测算算法,我们需要定义不同的具体测算实例类:

public class EqualPrinicipalStrategy implements InterestCalStrategy {
    @Override
    public List<CashFlow> calInterest(List<Principal> prinicipalList) {
        // 具体的测算逻辑
    }
}

public class EqualInterestStrategy implements InterestCalStrategy {
    @Override
    public List<CashFlow> calInterest(List<Principal> prinicipalList) {
        // 具体的测算逻辑
    }
}

对于所处的上下文来讲,它只需要持有对应测算算法的引用即可:

public class ApplicationContext {
    private InterestCalStrategy strategy;
    
    public void setStrategy(InterestCalStrategy strategy) {
        this.strategy = strategy;
    }
    
    public List<CashFlow> calInterest(List<Principal> prinicipalList) {
        return strategy.calInterest(prinicipalList);
    }
}

实际使用时只需要由客户端选取对应的策略进行测算即可:

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new ApplicationContext();
        // 等额本金的算法计算
        context.setStrategy(new EqualPrinicipalStrategy());
        context.calInterest(obtainPrinicipals());
        
        //  等额本息的计算
        context.setStrategy(new EqualInterestStrategy());
        context.calInterest(obtainPrinicipals());
    }
}

总结

策略模式的使用可以减少一些冗余的 if{}else{} 的使用,看起来和 "命令模式" 很相似。实际上这两个模式的最大区别在于 “命令模式” 强调需要做什么,而 “策略模式” 则在强调需要怎么做


参考:

[1] 《设计模式—可复用面向对象基础》

[2] https://stackoverflow.com/questions/4834979/difference-between-strategy-pattern-and-command-pattern

posted @ 2023-04-16 21:14  FatalFlower  阅读(21)  评论(0编辑  收藏  举报