设计模式之策略模式

前言

本文聊聊 行为型模式中的策略模式。策略模式就是定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。策略模式使得算法可独立于使用它的客户而变化。

UML

设计模式之策略模式

代码案例

// Strategy 策略接口,定义策略的抽象
public interface Strategy {
    Integer discount(Integer money);
}
// 策略A
public class StrategyA implements Strategy {
    @Override
    public Integer discount(Integer money) {
        return money / 10;
    }
}
// 策略B
public class StrategyB implements Strategy {
    @Override
    public Integer discount(Integer money) {
        return money - 20;
    }
}
// Content 上下文类,持有具体策略类的实例,并负责调用相关的算法 
public class StrategyContent {
    // 包含一个策略 
    private Strategy strategy;

   // 根据客户端传来的策略进行相应处理
    public StrategyContent(Strategy strategy) {
        this.strategy = strategy;
    }

    public  Integer discount(Integer money) {
        return this.strategy.discount(money);
    }
}
// 测试
public class StrategyTest {
    public static void main(String[] args) {
        Strategy strategy = new StrategyA();
        // 客户端将想要用的算法传入Content
        StrategyContent strategyContent = new StrategyContent(strategy);
        // 相应计算
        System.out.println(strategyContent.discount(100));
    }
}

源码中的应用

JDK中Arrays.sort(T[] a, Comparator<? super T> c)这个排序方法,它在内部实现了TimSort排序,但是,排序算法在比较两个元素大小的时候,需要借助我们传入的Comparator对象,才能完成比较。因此,这里的策略是指比较两个元素大小的策略,可以是忽略大小写比较,可以是倒序比较,也可以根据字符串长度比较。

如果我们想忽略大小写排序,就传入String::compareToIgnoreCase,如果我们想倒序排序,就传入(s1, s2) -> -s1.compareTo(s2),这个比较两个元素大小的算法就是策略。

优缺点

用户可以在不修改原有系统的基础上选择算法(策略),并且可以灵活地增加新的算法(策略)。符合开闭原则,对算法的开发。

但传统的策略模式实现方式中,客户端必须知道所有的具体策略类,并须自行显示决定使用哪一个策略类。

策略模式是将一系列的算法封装起来,让他们可以相互替换。可以避免一些if else 语句的处理,我们只需要在需要的场景下选择需要的策略。但是那些场景的判断时也是if else 来判断时,我们可以选择工厂模式来将"条件"进行封装,让我们只需要传入我们的条件来返回相应的策略。也就是策略和工厂的组合,策略也可以搭配单例返回同一个策略,不用过多的new对象了。

参考博客
  • www.liaoxuefeng.com