策略模式,如春风吹过,随心所欲,变幻无穷,每一丝风都是一种选择。
文章目录
- 一、订单处理
- 二、策略模式
- 三、策略模式的核心组成
- 四、运用策略模式
- 五、策略模式的应用场景
- 六、小结
- 推荐阅读
一、订单处理
场景假设:有一个订单处理系统,需要根据不同的订单类型(如普通订单、VIP 订单、超级 VIP 订单)来计算订单的折扣金额。
class OrderProcessor {
public double calculateDiscount(Order order) {
double originalPrice = order.getTotalPrice();
double discount = 0.0;
if (order.getType() == OrderType.REGULAR) {
// 正常订单折扣计算
discount = originalPrice * 0.1;
} else if (order.getType() == OrderType.VIP) {
// VIP 订单折扣计算
discount = originalPrice * 0.2;
} else if (order.getType() == OrderType.SUPER_VIP) {
// 超级 VIP 订单折扣计算
discount = originalPrice * 0.3;
} // ... 更多订单类型
return discount;
}
}
上面的代码虽然能够实现需求,但存在以下问题:
- 可扩展性差:如果需要添加更多的订单类型,我们必须修改原有的代码,违反了开放-封闭原则。
- 代码重复:不同订单类型的折扣计算逻辑被硬编码在同一个方法中,导致代码重复。
二、策略模式
策略模式(Strategy Pattern)是一种行为型
设计模式,它允许在运行时选择算法的行为。在策略模式中,可以定义一系列的算法,把它们封装起来,并且使它们可以互相替换。这样,客户端在使用算法时可以根据需求动态地选择其中一种算法,而不需要更改其代码。
三、策略模式的核心组成
策略模式的核心组成部分包括以下几个要素:
- 策略接口(Strategy Interface):这是一个接口或抽象类,定义所有具体策略类必须实现的方法。策略接口通常会声明一个或多个方法,用于执行具体的算法或操作。
- 具体策略类(Concrete Strategies):这些类实现了策略接口,每个具体策略类都代表一个独立的算法或操作。它们实现了策略接口中定义的方法,提供了算法的具体实现。
- 上下文(Context):上下文类持有一个策略接口的引用,通常会包含一个设置策略的方法,用于动态地切换不同的具体策略。上下文类通过策略接口与具体策略类进行交互,根据需要调用具体策略类的方法。
- 客户端(Client):客户端是使用策略模式的类或模块。它通过实例化上下文对象,并设置具体策略类来使用相应的算法或操作。
这个类图展示了策略模式的核心组成部分:
Strategy
接口定义了所有具体策略类必须实现的算法方法algorithm()
。ConcreteStrategyA
和ConcreteStrategyB
是具体的策略类,实现了 Strategy 接口,分别提供了不同的算法实现。Context
类持有一个 Strategy 接口的引用,在运行时可以动态地切换具体的策略。它提供了一个setStrategy()
方法来设置当前的策略,并且通过contextInterface()
方法调用当前策略的算法。
四、运用策略模式
场景假设:有一个订单处理系统,需要根据不同的订单类型(如普通订单、VIP 订单、超级 VIP 订单)来计算订单的折扣金额。
-
定义抽象策略接口:首先,我们需要定义一个抽象策略接口,该接口包含一个计算折扣价格的方法。这个接口将作为不同折扣策略的基类。
// 抽象策略接口 interface DiscountStrategy { double calculateDiscount(double originalPrice); }
-
创建具体策略类:接下来,我们为不同的折扣方式创建具体策略类。每个具体策略类都实现了折扣策略接口,并提供了自己的折扣计算逻辑。
// 正常折扣策略 class RegularDiscountStrategy implements DiscountStrategy { @Override public double calculateDiscount(double originalPrice) { // 根据正常折扣计算折后价格 return originalPrice * 0.9; } } // VIP 折扣策略 class VIPDiscountStrategy implements DiscountStrategy { @Override public double calculateDiscount(double originalPrice) { // VIP 折扣计算 return originalPrice * 0.8; } } // 超级 VIP 折扣策略 class SuperVIPDiscountStrategy implements DiscountStrategy { @Override public double calculateDiscount(double originalPrice) { // 超级 VIP 折扣计算 return originalPrice * 0.7; } }
-
创建环境类:我们需要一个环境类来持有策略对象,并根据客户端的选择来执行相应的策略。
// 环境类 class OrderProcessor { private DiscountStrategy discountStrategy; public void setDiscountStrategy(DiscountStrategy strategy) { this.discountStrategy = strategy; } public double calculateDiscountedPrice(double originalPrice) { return discountStrategy.calculateDiscount(originalPrice); } }
-
客户端代码:在客户端代码中,我们可以根据订单类型选择不同的折扣策略。
public class Client { public static void main(String[] args) { OrderProcessor orderProcessor = new OrderProcessor(); // 选择不同的折扣策略 orderProcessor.setDiscountStrategy(new RegularDiscountStrategy()); double discountedPrice1 = orderProcessor.calculateDiscountedPrice(100.0); System.out.println("正常折扣后价格:" + discountedPrice1); orderProcessor.setDiscountStrategy(new VIPDiscountStrategy()); double discountedPrice2 = orderProcessor.calculateDiscountedPrice(100.0); System.out.println("VIP 折扣后价格:" + discountedPrice2); } }
五、策略模式的应用场景
策略模式常见于以下场景:
- 行为切换:当系统中有多个类,这些类之间的区别仅在于它们的行为不同时,可以使用策略模式。通过策略模式,用户对象可以在这些行为中动态地选择一个,将不同的行为封装到不同的类中,每个行为对应一种策略。
- 算法选择:如果系统中需要在几种算法中动态地选择一种,策略模式也适用。例如,计算方式可以有不同的实现,比如加法策略和乘法策略,用户可以根据需要选择不同的策略。
六、小结
策略模式是一种简单但非常实用的设计模式,它能有效地管理算法的选择和切换,提高系统的灵活性和可维护性。在面对需要动态选择算法或行为的问题时,策略模式是一个值得考虑的解决方案。
推荐阅读
- Spring 三级缓存
- 深入了解 MyBatis 插件:定制化你的持久层框架
- Zookeeper 注册中心:单机部署
- 【JavaScript】探索 JavaScript 中的解构赋值
- 深入理解 JavaScript 中的 Promise、async 和 await