欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 策略模式 (Strategy)详解

策略模式 (Strategy)详解

2025/2/24 8:12:04 来源:https://blog.csdn.net/nmsoftklb/article/details/145771420  浏览:    关键词:策略模式 (Strategy)详解

一、什么是策略模式?

  • 定义: 策略模式是一种行为型设计模式。 它定义了一系列算法,将每个算法封装起来,并使它们可以相互替换。
  • 核心思想: 将算法的定义与使用分离。 客户端代码不直接调用具体的算法,而是通过一个统一的接口(策略接口)来访问不同的算法。
  • 意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

二、策略模式的结构

策略模式通常包含以下几个角色:

  1. Context (环境/上下文):

    • 维护一个对 Strategy 对象的引用。
    • 定义客户端使用的接口。
    • 可以包含一些与算法无关的业务逻辑。
    • 不直接与具体策略类交互,而是通过 Strategy 接口与策略类交互。
  2. Strategy (策略接口):

    • 定义所有支持的算法的公共接口。
    • 通常是一个接口或抽象类。
  3. ConcreteStrategy (具体策略):

    • 实现 Strategy 接口,提供具体的算法实现。
    • 可以有多个 ConcreteStrategy 类,每个类实现一种不同的算法。

UML 类图:

+-----------------+         +-----------------+       +---------------------+
|     Context     |-------->|   <<Strategy>>   |       |   ConcreteStrategyA |
+-----------------+         +-----------------+       +---------------------+
| -strategy       |         | +algorithm()    |------>| +algorithm()        |
+-----------------+         +-----------------+       +---------------------+
| +contextInterface()|                                   
+-----------------+                                   +---------------------+|   ConcreteStrategyB |+---------------------+| +algorithm()        |+---------------------++---------------------+|   ConcreteStrategyC |+---------------------+| +algorithm()        |+---------------------+

三、策略模式的实现 (Java)

// 策略接口
interface PaymentStrategy {void pay(int amount);
}// 具体策略类 - 支付宝支付
class AlipayStrategy implements PaymentStrategy {private String email;private String password;public AlipayStrategy(String email, String password) {this.email = email;this.password = password;}@Overridepublic void pay(int amount) {System.out.println("Paid " + amount + " using Alipay.");// ... 支付宝支付的具体逻辑 ...}
}// 具体策略类 - 微信支付
class WeChatPayStrategy implements PaymentStrategy {private String appId;private String secretKey;public WeChatPayStrategy(String appId, String secretKey) {this.appId = appId;this.secretKey = secretKey;}@Overridepublic void pay(int amount) {System.out.println("Paid " + amount + " using WeChat Pay.");// ... 微信支付的具体逻辑 ...}
}// 具体策略类 - 银行卡支付
class CreditCardStrategy implements PaymentStrategy {private String cardNumber;private String cvv;private String dateOfExpiry;public CreditCardStrategy(String cardNumber, String cvv, String dateOfExpiry) {this.cardNumber = cardNumber;this.cvv = cvv;this.dateOfExpiry = dateOfExpiry;}@Overridepublic void pay(int amount) {System.out.println("Paid " + amount + " using Credit Card.");// ... 银行卡支付的具体逻辑 ...}
}// 上下文类
class ShoppingCart {private List<Item> items;private PaymentStrategy paymentStrategy; // 持有策略接口的引用public ShoppingCart() {this.items = new ArrayList<>();}public void addItem(Item item) {this.items.add(item);}public void removeItem(Item item) {this.items.remove(item);}public int calculateTotal() {int sum = 0;for (Item item : items) {sum += item.getPrice();}return sum;}// 设置支付策略public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}// 使用支付策略进行支付public void pay() {int amount = calculateTotal();paymentStrategy.pay(amount); // 通过策略接口调用具体算法}
}// 商品类 (示例)
class Item {private String upcCode;private int price;public Item(String upcCode, int price) {this.upcCode = upcCode;this.price = price;}public String getUpcCode() {return upcCode;}public int getPrice() {return price;}
}// 客户端代码
public class StrategyPatternExample {public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();Item item1 = new Item("1234", 10);Item item2 = new Item("5678", 40);cart.addItem(item1);cart.addItem(item2);// 使用支付宝支付cart.setPaymentStrategy(new AlipayStrategy("myemail@example.com", "mypwd"));cart.pay();// 使用微信支付cart.setPaymentStrategy(new WeChatPayStrategy("myAppId", "mySecretKey"));cart.pay();// 使用银行卡支付cart.setPaymentStrategy(new CreditCardStrategy("1234567890123456", "786", "12/24"));cart.pay();}
}

代码解释:

  • PaymentStrategy (策略接口): 定义了支付的公共接口 pay()
  • AlipayStrategyWeChatPayStrategyCreditCardStrategy (具体策略): 实现了 PaymentStrategy 接口,提供了不同的支付方式。
  • ShoppingCart (上下文): 维护了一个 PaymentStrategy 类型的引用,可以在运行时设置不同的支付策略。 pay() 方法通过 paymentStrategy 对象调用具体的支付算法。

四、策略模式的优缺点

优点:

  • 开闭原则: 增加新的策略非常方便,无需修改原有代码,只需要添加新的具体策略类即可。
  • 避免使用多重条件判断: 将不同的算法封装到不同的策略类中,避免了使用 if-elseswitch-case 等多重条件判断语句。
  • 提高算法的复用性: 不同的策略类可以被多个上下文对象复用。
  • 提高算法的保密性: 客户端不需要知道算法的具体实现细节。
  • 松耦合: 算法的定义与使用分离,降低了代码的耦合度。

缺点:

  • 客户端必须知道所有的策略类: 客户端需要知道所有的策略类,并选择合适的策略类。
  • 增加类的数量: 每增加一个策略,就需要增加一个具体策略类,可能会导致类的数量过多。
  • 只适用于算法或行为的选择: 策略模式只适用于封装算法或行为,不适用于封装对象的状态。
  • 策略间通信: 如果策略之间需要共享数据或进行通信,可能需要额外的机制来处理。

五、策略模式的适用场景

  • 需要在运行时动态地选择算法: 例如,根据用户的选择、系统配置或外部条件来选择不同的算法。
  • 有多种算法或行为可供选择: 例如,排序算法(冒泡排序、快速排序、归并排序)、压缩算法(ZIP、GZIP、RAR)、加密算法(AES、DES、RSA)等。
  • 需要避免使用多重条件判断语句: 如果代码中存在大量的 if-elseswitch-case 语句来根据不同的条件选择不同的算法,可以考虑使用策略模式。
  • 需要对客户端隐藏算法的具体实现细节: 可以将算法的实现细节封装在策略类中,只向客户端暴露策略接口。

六、策略模式的应用示例

  1. 排序算法: 定义一个排序策略接口,不同的排序算法(例如冒泡排序、快速排序、归并排序)实现该接口。 客户端可以根据需要选择不同的排序算法。
  2. 压缩算法: 定义一个压缩策略接口,不同的压缩算法(例如 ZIP、GZIP、RAR)实现该接口。 客户端可以根据需要选择不同的压缩算法。
  3. 加密算法: 定义一个加密策略接口,不同的加密算法(例如 AES、DES、RSA)实现该接口。 客户端可以根据需要选择不同的加密算法。
  4. 支付方式: 定义一个支付策略接口,不同的支付方式(例如支付宝、微信支付、银行卡支付)实现该接口。 客户端可以根据需要选择不同的支付方式。
  5. Java I/O 中的 Comparator 接口: Comparator 接口定义了比较两个对象的方法。 可以创建不同的 Comparator 实现类来定义不同的比较策略。

七、策略模式 vs. 模板方法模式 vs. 状态模式

  • 策略模式 (Strategy): 关注的是 算法的替换,通过组合和接口来实现算法的切换。
  • 模板方法模式 (Template Method): 关注的是 算法的骨架,通过继承和重写来实现算法的可变部分。
  • 状态模式 (State): 关注的是 对象的状态变化,通过状态对象来改变对象的行为。

区别:

特征策略模式模板方法模式状态模式
关注点算法选择算法骨架对象状态
实现方式组合/委托继承组合/委托
可变部分不同的策略类实现相同的接口子类实现抽象方法或覆盖钩子方法不同的状态类实现相同的接口
算法结构策略类定义算法,客户端选择具体的策略模板方法定义算法结构,子类实现具体步骤状态类定义状态下的行为,Context 对象根据状态切换行为
控制反转
适用场景定义一系列算法,并在运行时动态选择算法定义算法骨架,部分步骤延迟到子类实现对象行为取决于状态,且状态变化复杂

总结:

策略模式是一种非常有用的设计模式,它可以将算法的定义与使用分离,提高代码的可扩展性、可维护性和可复用性。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词