Featured image of post 策略模式

策略模式

📖 介绍

策略模式是一种行为型模式

策略模式指定义一系列算法,每种算法都封装到不同的类中,在运行时,可以灵活地替换这些的算法(替换执行的策略)。

📖 常见的场景:

  • 🔖 旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。

  • 🔖 电商系统中,下单时,可以选择多种则扣策略(满减,优惠券,积分);支付时,可以选择多种支付方式(支付宝,微信,云闪付)。

  • 🔖 用策略模式消除大量的 if-else

🎈 实现方式

  • 🎗️ 策略接口:使用接口定义具体策略的通用接口,声明了一个上下文用于执行策略的方法。

  • 🎗️ 具体策略:实现策略接口,实现具体的相关算法。

  • 🎗️ 客户端调用时,会将使用具体的策略对象传递给上下文,根据策略,执行不同的算法。

💡 重点:实现同一个接口,通过传入的策略,执行不同的算法。

🛠️ 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 策略接口
public interface DiscountStrategy {
    // 获取优惠金额
    BigDecimal getDiscount(BigDecimal total);  
}

// 打折优惠
public class UserDiscountStrategy implements DiscountStrategy {
    public BigDecimal getDiscount(BigDecimal total) {
        return total.multiply(new BigDecimal("0.1")).setScale(2, RoundingMode.DOWN);
    }
}

// 满减优惠
public class OverDiscountStrategy implements DiscountStrategy {
    public BigDecimal getDiscount(BigDecimal total) {
        return total.compareTo(BigDecimal.valueOf(100)) >= 0 ? BigDecimal.valueOf(20) : BigDecimal.ZERO;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 用于执行策略的上下文
public class DiscountContext {
    // 持有某种策略
    private DiscountStrategy strategy = new UserDiscountStrategy();

    public DiscountContext(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    // 用于更改策略方式
    public void setStrategy(DiscountStrategy strategy) {
        this.strategy = strategy;
    }

    // 计算付款金额
    public BigDecimal calculatePrice(BigDecimal total) {
        return total.subtract(this.strategy.getDiscount(total)).setScale(2);
    }
}
1
2
3
4
5
6
7
8
// 使用策略模式
DiscountContext context = new DiscountContext();

BigDecimal price = BigDecimal.valueOf(100);

// 使用满减策略
context.setStrategy(new OverDiscountStrategy());
BigDecimal pay = context.calculatePrice(price);

☕ Java 中的策略模式

以排序为例,在 java.util.Arrays java.util.Collections 工具类中 的 sort(XX, Comparator) 方法:

1
2
3
public static <T> void sort(T[] a, Comparator<? super T> c) {
    // ...
}

普通的 sort() 默认从小到大进行排序,如果我们想要从大到小进行排序,就是要更改排序的 策略,我们可以实现这个 Comparatorint compare(T o1, T o2) 方法,并传入 sort()

1
Arrays.sort(nums, (o1, o2) -> o2 - o1);

🔗 参考