【Java教程】Day20-21 设计模式:行为型模式——策略模式
1. 引言
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列的算法,将它们封装起来,并使得它们可以相互替换。策略模式的主要目的是使得算法可以独立于使用它的客户而变化。它常用于需要根据不同条件选择不同算法的场景。
在Java的标准库中,策略模式得到了广泛的应用,特别是在排序等常见操作中。通过策略模式,我们可以在运行时动态选择算法,而不需要修改原有代码。
2. 策略模式的结构
策略模式包含以下几个核心部分:
-
策略接口(Strategy):定义一组算法或行为的接口。
-
具体策略类(ConcreteStrategy):实现策略接口,封装具体的算法。
-
上下文类(Context):持有一个策略对象,并提供方法来切换策略,供客户端使用。
2.1 策略接口
策略接口定义了算法的公共方法,供具体策略类实现:
javapublic interface DiscountStrategy {// 计算折扣额度:BigDecimal getDiscount(BigDecimal total);}
2.2 具体策略类
不同的策略实现该接口,根据不同的规则进行计算。我们可以实现多个策略,例如普通用户折扣、满减折扣等。
javapublic class UserDiscountStrategy implements DiscountStrategy {public BigDecimal getDiscount(BigDecimal total) {// 普通会员打九折:return total.multiply(new BigDecimal("0.1")).setScale(2, RoundingMode.DOWN);}}
javapublic class OverDiscountStrategy implements DiscountStrategy {public BigDecimal getDiscount(BigDecimal total) {// 满100减20优惠:return total.compareTo(BigDecimal.valueOf(100)) >= 0 ? BigDecimal.valueOf(20) : BigDecimal.ZERO;}}
2.3 上下文类
上下文类持有一个策略对象,并允许在运行时根据需求切换策略:
javapublic class DiscountContext {// 默认使用普通会员折扣private DiscountStrategy strategy = new UserDiscountStrategy();// 允许客户端设置新策略:public void setStrategy(DiscountStrategy strategy) {this.strategy = strategy;}// 计算价格方法public BigDecimal calculatePrice(BigDecimal total) {return total.subtract(this.strategy.getDiscount(total)).setScale(2);}}
2.4 使用示例
使用策略模式的核心优势是可以灵活地切换策略。以下是一个完整的示例,展示了如何根据不同的折扣策略计算购物车总价。
javapublic class Main {public static void main(String[] args) {DiscountContext ctx = new DiscountContext();// 默认使用普通会员折扣BigDecimal pay1 = ctx.calculatePrice(BigDecimal.valueOf(105));System.out.println("普通会员折扣: " + pay1);// 使用满减折扣ctx.setStrategy(new OverDiscountStrategy());BigDecimal pay2 = ctx.calculatePrice(BigDecimal.valueOf(105));System.out.println("满减折扣: " + pay2);// 使用Prime会员折扣ctx.setStrategy(new PrimeDiscountStrategy());BigDecimal pay3 = ctx.calculatePrice(BigDecimal.valueOf(105));System.out.println("Prime会员折扣: " + pay3);}}
2.5 输出示例
text普通会员折扣: 94.50满减折扣: 85.00Prime会员折扣: 80.00
3. 策略模式的应用场景
策略模式非常适用于以下几种场景:
-
需要多种算法的场景:如果有多个算法可以执行同样的任务(例如排序、折扣计算等),策略模式可以将这些算法封装起来,并在运行时进行选择。
-
算法或行为变化频繁:当系统中算法或行为会频繁变化时,使用策略模式可以避免修改现有代码,只需添加新的策略类即可。
-
避免大量的
if-else判断:当不同条件下执行不同的行为时,策略模式可以避免复杂的条件判断,增强代码的可维护性。
4. Java标准库中的策略模式应用
策略模式在Java的标准库中有很多应用,最典型的就是Arrays.sort()方法的实现。我们来看一个例子,如何使用策略模式实现忽略大小写的排序。
javaimport java.util.Arrays;public class Main {public static void main(String[] args) {String[] array = { "apple", "Pear", "Banana", "orange" };Arrays.sort(array, String::compareToIgnoreCase); // 使用忽略大小写的排序策略System.out.println(Arrays.toString(array));}}
这里,Arrays.sort()方法接收一个Comparator对象,它就是一种策略。在排序时,可以传入不同的比较策略,例如按字典顺序排序,按字符串长度排序等。
javaArrays.sort(array, (s1, s2) -> -s1.compareTo(s2)); // 使用倒序排序策略
5. 策略模式的优缺点
5.1 优点
-
增强了灵活性:策略模式允许在运行时动态选择不同的策略算法,这使得系统更加灵活。
-
符合开闭原则:通过扩展策略类来增加新功能,不需要修改现有的代码。
-
简化代码:避免了大量的
if-else或switch语句,使代码更加简洁和可维护。
5.2 缺点
-
增加了类的数量:每一种策略都需要定义一个具体的策略类,当策略多时,会增加类的数量。
-
客户端需要知道所有的策略:客户端需要知道有哪些策略,并负责选择使用哪个策略。
6. 小结
策略模式的核心思想是将算法封装在独立的策略类中,使得算法可以在运行时被动态切换。通过策略模式,我们能够实现不同策略之间的灵活切换,避免了冗长的if-else或switch语句,使得代码更加简洁和易于维护。策略模式在实际项目中有广泛的应用,特别是在需要根据不同条件选择不同算法或行为时,非常有效。
通过扩展策略,可以轻松地增加新的行为,而不需要修改现有的代码,符合开闭原则,使得系统更具扩展性。
7. 练习
假设网站对于Prime会员的折扣规则是:在满100减20的基础上,再对Prime会员进行七折优惠。请实现这一新策略,并将其与其他策略结合使用。
更多推荐

所有评论(0)