前言:
在我们日常的开发中,我们往往会遇到如下问题: 在一个类中需要根据不同的情况选择不同的行为时,我们可能会使用大量的条件判断(如 if-else 或 switch-case)。这种做法虽然也可以,但当需求扩展或变动时,会引发以下问题:
- 高耦合:条件判断将行为与业务逻辑紧密绑定在一起,导致代码变得难以修改和扩展。
- 低可维护性:每次添加新的行为或变化时,我们都需要修改原有的类,导致代码出现不必要的重复和冗余。
- 难以测试:由于多个行为被紧密耦合在一起,单独测试某一算法变得复杂。
为了解决这些问题,策略设计模式应运而生。它允许将行为封装到独立的策略类中,从而使得系统的各个部分相对独立,能够单独修改、替换和扩展。
策略设计模式的实现
在策略设计模式中,我们通常会定义一个通用的策略接口,所有具体的策略类都会实现这个接口,然后,我们在上下文类中持有一个对策略接口的引用,并通过设置不同的策略对象来动态改变行为。
不使用策略设计模式案例
考虑一个电子商务系统,其中用户可以选择不同的支付方式:信用卡支付、支付宝支付、微信支付。如果我们没有使用策略设计模式,可能会写出类似下面的实现:
流程图:
使用示例
- ShoopingCart 类
public class ShoppingCart {
private String paymentMethod;
public ShoppingCart(String paymentMethod) {
this.paymentMethod = paymentMethod;
}
public void checkout(int amount) {
if (paymentMethod.equals("CreditCard")) {
System.out.println("使用信用卡支付 " + amount + " 元。");
} else if (paymentMethod.equals("AliPay")) {
System.out.println("使用支付宝支付 " + amount + " 元。");
} else if (paymentMethod.equals("WeChatPay")) {
System.out.println("使用微信支付 " + amount + " 元。");
} else {
System.out.println("未选择有效的支付方式。");
}
}
}
checkout 方法:这个方法模拟结账操作。它根据 paymentMethod 的值来判断使用哪种支付方式。它的逻辑如下:
- 如果支付方式是 CreditCard,则打印使用信用卡支付的提示。
- 如果支付方式是 AliPay,则打印使用支付宝支付的提示。
- 如果支付方式是 WeChatPay,则打印使用微信支付的提示。
- 如果支付方式是其他的字符串,打印 "未选择有效的支付方式." 提示无效支付方式。
执行代码
public class SpiApplication {
public static void main(String[] args) {
// 创建使用信用卡支付的购物车
ShoppingCart cart1 = new ShoppingCart("CreditCard");
cart1.checkout(1000);
// 创建使用支付宝支付的购物车
ShoppingCart cart2 = new ShoppingCart("AliPay");
cart2.checkout(500);
// 创建使用微信支付的购物车
ShoppingCart cart3 = new ShoppingCart("WeChatPay");
cart3.checkout(750);
// 创建使用无效支付方式的购物车
ShoppingCart cart4 = new ShoppingCart("PayPal");
cart4.checkout(300);
}
}
输出结果
使用信用卡支付 1000 元。
使用支付宝支付 500 元。
使用微信支付 750 元。
未选择有效的支付方式。
存在的问题
扩展困难:每当我们需要增加新的支付方式时,都需要修改 ShoppingCart 类,增加新的条件判断。这个操作违背了开闭原则(对修改关闭,对扩展开放)。
维护难度大:随着支付方式的增多,ShoppingCart 类会变得越来越庞大,难以维护。
缺乏灵活性:如果用户希望在运行时选择不同的支付方式,我们的代码很难做到动态切换。
假设我们要为 ShoppingCart 类添加一个新的支付方式——CloudQuickPass,即“云闪付”。我们需要在 ShoppingCart 类中增加一个新的 else if 条件判断,如下所示:
扩展后的 ShoppingCart 类:
public void checkout(int amount) {
if (paymentMethod.equals("CreditCard")) {
System.out.println("使用信用卡支付 " + amount + " 元。");
} else if (paymentMethod.equals("CloudQuickPass")) {
System.out.println("使用云闪付支付 " + amount + " 元。");
} xxx
}
增加后的流程图
使用策略设计模式案例
引入策略模式后,我们将每一种支付方式抽成一个独立的策略类,并在 ShoppingCart 中设置不同的策略对象来决定支付对象:
使用案例
- PaymentStrategy 接口
public interface PaymentStrategy {
void pay(int amount);
}
- 具体支付策略接口
// 具体支付策略
// 信用卡支付实现
public class CreditCardPayment implements PaymentStrategy {
@Override
public void pay(int amount) {
System.out.println("使用信用卡支付 " + amount + " 元。");
}
}
// 支付宝支付实现
public class AliPayPayment implements PaymentStrategy {
@Override
public void pay(int amount) {
System.out.println("使用支付宝支付 " + amount + " 元。");
}
}
// 微信支付实现
public class WeChatPayPayment implements PaymentStrategy {
@Override
public void pay(int amount) {
System.out.println("使用微信支付 " + amount + " 元。");
}
}
- 修改 ShoopingCart 类
public class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout(int amount) {
if (paymentStrategy == null) {
System.out.println("未选择有效的支付方式");
return;
}
paymentStrategy.pay(amount);
}
}
执行代码
public class SpiApplication {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 用户选择使用信用卡支付
cart.setPaymentStrategy(new CreditCardPayment());
cart.checkout(1000);
// 用户选择使用支付宝支付
cart.setPaymentStrategy(new AliPayPayment());
cart.checkout(500);
// 用户选择使用微信支付
cart.setPaymentStrategy(new WeChatPayPayment());
cart.checkout(750);
}
}
输出结果
使用信用卡支付 1000 元。
使用支付宝支付 500 元。
使用微信支付 750 元。
使用策略者设置模型扩展 CloudQuickPass,即“云闪付”。
增加一个实现类
// 云闪付支付
public class CloudQuickPassPayment implements PaymentStrategy {
@Override
public void pay(int amount) {
System.out.println("使用云闪付支付 " + amount + " 元。");
}
}
此时关系图
总结
使用策略者模式之后,扩展新的支付方式不再需要修改现有的 ShoppingCart 类,也不再需要增加条件判断,每一次增加的支付方式的时候,我们只需要创建一个新的策略类,并注入到 ShoppingCart 中。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。