拓冰建站拓冰建站
首页 / 资讯中心 / 正文

策略模式详解:从设计原则到支付系统实战应用

在技术开发领域策略模式Strategy Pattern是一种常见的设计模式它允许在运行时选择算法或行为。本文将围绕隐藏在大象背后这一策略展开详细讲解如何在实际项目中应用策略模式来解耦代码、提高可维护性。无论你是刚接触设计模式的初学者还是希望优化现有架构的资深开发者本文都将提供完整的代码示例和实战案例帮助你掌握这一核心设计思想。1. 策略模式基础概念1.1 什么是策略模式策略模式属于行为型设计模式它定义了一系列算法并将每个算法封装起来使它们可以相互替换。这种模式让算法的变化独立于使用算法的客户端。在实际开发中我们经常遇到需要根据不同条件执行不同算法的场景。比如支付系统中根据用户选择的不同支付方式支付宝、微信、银行卡执行不同的支付逻辑。如果使用if-else或switch-case硬编码会导致代码臃肿且难以维护。1.2 策略模式的三大要素策略模式包含三个核心角色策略接口Strategy Interface定义所有支持的算法或行为的公共接口具体策略类Concrete Strategies实现策略接口的具体算法类上下文类Context持有一个策略对象的引用通过接口与具体策略交互1.3 为什么需要隐藏在大象背后隐藏在大象背后这个比喻形象地描述了策略模式的核心价值——将复杂的算法实现细节隐藏起来只暴露简单的接口。就像大象的身体可以隐藏许多复杂的功能对外却只展示统一的行为接口。这种设计带来的好处包括降低耦合度算法实现与使用分离提高扩展性新增策略无需修改现有代码增强可维护性每个策略类职责单一便于测试和维护2. 环境准备与开发配置2.1 开发环境要求本文示例基于Java语言实现但策略模式的概念适用于所有面向对象编程语言。基础环境要求如下JDK版本1.8或以上构建工具Maven 3.6 或 Gradle 6.0IDE推荐IntelliJ IDEA、Eclipse或VS Code项目类型普通的Java项目无需特殊框架依赖2.2 项目结构规划在开始编码前我们先规划项目包结构src/main/java/ ├── strategy/ │ ├── context/ │ │ └── PaymentContext.java │ ├── strategy/ │ │ ├── PaymentStrategy.java │ │ ├── AlipayStrategy.java │ │ ├── WechatPayStrategy.java │ │ └── BankCardStrategy.java │ └── client/ │ └── StrategyClient.java2.3 依赖配置如果使用Mavenpom.xml只需要基础配置?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdcom.example/groupId artifactIdstrategy-pattern-demo/artifactId version1.0-SNAPSHOT/version properties maven.compiler.source1.8/maven.compiler.source maven.compiler.target1.8/maven.compiler.target project.build.sourceEncodingUTF-8/project.build.sourceEncoding /properties /project3. 策略模式核心实现3.1 定义策略接口策略接口是模式的核心它定义了所有具体策略必须实现的方法。// 文件路径src/main/java/strategy/strategy/PaymentStrategy.java package strategy.strategy; /** * 支付策略接口 * 定义统一的支付方法规范 */ public interface PaymentStrategy { /** * 执行支付操作 * param amount 支付金额 * return 支付结果 */ boolean pay(double amount); /** * 获取支付方式名称 * return 支付方式描述 */ String getStrategyName(); }3.2 实现具体策略类接下来我们实现三个具体的支付策略类。支付宝支付策略// 文件路径src/main/java/strategy/strategy/AlipayStrategy.java package strategy.strategy; /** * 支付宝支付具体策略 */ public class AlipayStrategy implements PaymentStrategy { private String accountId; public AlipayStrategy(String accountId) { this.accountId accountId; } Override public boolean pay(double amount) { System.out.println(使用支付宝支付 amount 元); System.out.println(支付宝账户 accountId); // 模拟支付宝支付逻辑 boolean success simulatePaymentProcess(amount); if (success) { System.out.println(支付宝支付成功); return true; } else { System.out.println(支付宝支付失败); return false; } } Override public String getStrategyName() { return 支付宝支付; } private boolean simulatePaymentProcess(double amount) { // 模拟支付处理实际项目中会调用支付宝API return amount 0; // 金额大于0则支付成功 } }微信支付策略// 文件路径src/main/java/strategy/strategy/WechatPayStrategy.java package strategy.strategy; /** * 微信支付具体策略 */ public class WechatPayStrategy implements PaymentStrategy { private String openId; public WechatPayStrategy(String openId) { this.openId openId; } Override public boolean pay(double amount) { System.out.println(使用微信支付 amount 元); System.out.println(微信OpenID openId); // 模拟微信支付逻辑 boolean success amount 0 amount 50000; // 单笔限额5万元 if (success) { System.out.println(微信支付成功); return true; } else { System.out.println(微信支付失败金额超限或无效); return false; } } Override public String getStrategyName() { return 微信支付; } }银行卡支付策略// 文件路径src/main/java/strategy/strategy/BankCardStrategy.java package strategy.strategy; /** * 银行卡支付具体策略 */ public class BankCardStrategy implements PaymentStrategy { private String cardNumber; private String bankName; public BankCardStrategy(String cardNumber, String bankName) { this.cardNumber cardNumber; this.bankName bankName; } Override public boolean pay(double amount) { System.out.println(使用银行卡支付 amount 元); System.out.println(银行 bankName 卡号 maskCardNumber(cardNumber)); // 模拟银行卡支付逻辑 boolean success validateCard() amount 0; if (success) { System.out.println(银行卡支付成功); return true; } else { System.out.println(银行卡支付失败卡号无效或金额错误); return false; } } Override public String getStrategyName() { return bankName 银行卡支付; } private boolean validateCard() { // 模拟银行卡验证逻辑 return cardNumber ! null cardNumber.length() 16; } private String maskCardNumber(String cardNumber) { if (cardNumber null || cardNumber.length() 8) return ***; return cardNumber.substring(0, 4) **** cardNumber.substring(cardNumber.length() - 4); } }3.3 创建上下文类上下文类负责维护策略对象的引用并提供接口供客户端调用。// 文件路径src/main/java/strategy/context/PaymentContext.java package strategy.context; import strategy.strategy.PaymentStrategy; /** * 支付上下文类 * 负责管理支付策略和执行支付操作 */ public class PaymentContext { private PaymentStrategy paymentStrategy; // 设置支付策略 public void setPaymentStrategy(PaymentStrategy paymentStrategy) { this.paymentStrategy paymentStrategy; } // 执行支付 public boolean executePayment(double amount) { if (paymentStrategy null) { throw new IllegalStateException(支付策略未设置); } System.out.println(开始执行支付...); System.out.println(使用策略 paymentStrategy.getStrategyName()); long startTime System.currentTimeMillis(); boolean result paymentStrategy.pay(amount); long endTime System.currentTimeMillis(); System.out.println(支付耗时 (endTime - startTime) ms); return result; } // 获取当前策略名称 public String getCurrentStrategyName() { return paymentStrategy ! null ? paymentStrategy.getStrategyName() : 未设置策略; } }4. 完整实战案例演示4.1 客户端调用示例下面我们创建一个客户端类来演示策略模式的使用。// 文件路径src/main/java/strategy/client/StrategyClient.java package strategy.client; import strategy.context.PaymentContext; import strategy.strategy.AlipayStrategy; import strategy.strategy.BankCardStrategy; import strategy.strategy.WechatPayStrategy; /** * 策略模式客户端演示类 */ public class StrategyClient { public static void main(String[] args) { // 创建支付上下文 PaymentContext context new PaymentContext(); System.out.println( 策略模式演示开始 ); // 演示支付宝支付 System.out.println(\n1. 支付宝支付演示); context.setPaymentStrategy(new AlipayStrategy(2088102568741234)); context.executePayment(100.50); // 演示微信支付 System.out.println(\n2. 微信支付演示); context.setPaymentStrategy(new WechatPayStrategy(oUpF8uMuAJO_M2pxb1Q9zNjWeS6o)); context.executePayment(200.00); // 演示银行卡支付 System.out.println(\n3. 银行卡支付演示); context.setPaymentStrategy(new BankCardStrategy(6225880134567890, 招商银行)); context.executePayment(500.75); // 演示支付失败场景 System.out.println(\n4. 支付失败场景演示); context.setPaymentStrategy(new WechatPayStrategy(invalid_openid)); boolean result context.executePayment(-50.00); // 无效金额 System.out.println(支付结果 (result ? 成功 : 失败)); System.out.println(\n 策略模式演示结束 ); } }4.2 运行结果分析运行上述客户端代码预期输出如下 策略模式演示开始 1. 支付宝支付演示 开始执行支付... 使用策略支付宝支付 使用支付宝支付100.5元 支付宝账户2088102568741234 支付宝支付成功 支付耗时Xms 2. 微信支付演示 开始执行支付... 使用策略微信支付 使用微信支付200.0元 微信OpenIDoUpF8uMuAJO_M2pxb1Q9zNjWeS6o 微信支付成功 支付耗时Xms 3. 银行卡支付演示 开始执行支付... 使用策略招商银行银行卡支付 使用银行卡支付500.75元 银行招商银行卡号6225****7890 银行卡支付成功 支付耗时Xms 4. 支付失败场景演示 开始执行支付... 使用策略微信支付 使用微信支付-50.0元 微信OpenIDinvalid_openid 微信支付失败金额超限或无效 支付结果失败 策略模式演示结束 4.3 动态策略切换演示策略模式最大的优势在于运行时动态切换策略。下面演示如何根据用户输入动态选择支付方式。// 文件路径src/main/java/strategy/client/DynamicStrategyClient.java package strategy.client; import strategy.context.PaymentContext; import strategy.strategy.AlipayStrategy; import strategy.strategy.BankCardStrategy; import strategy.strategy.PaymentStrategy; import strategy.strategy.WechatPayStrategy; import java.util.HashMap; import java.util.Map; import java.util.Scanner; /** * 动态策略切换演示 */ public class DynamicStrategyClient { private static MapString, PaymentStrategy strategyMap new HashMap(); static { // 初始化策略映射 strategyMap.put(1, new AlipayStrategy(2088102568741234)); strategyMap.put(2, new WechatPayStrategy(oUpF8uMuAJO_M2pxb1Q9zNjWeS6o)); strategyMap.put(3, new BankCardStrategy(6225880134567890, 招商银行)); } public static void main(String[] args) { PaymentContext context new PaymentContext(); Scanner scanner new Scanner(System.in); System.out.println( 动态策略选择演示 ); System.out.println(请选择支付方式); System.out.println(1 - 支付宝支付); System.out.println(2 - 微信支付); System.out.println(3 - 银行卡支付); System.out.print(请输入选择); String choice scanner.nextLine(); PaymentStrategy selectedStrategy strategyMap.get(choice); if (selectedStrategy ! null) { context.setPaymentStrategy(selectedStrategy); System.out.print(请输入支付金额); double amount scanner.nextDouble(); boolean result context.executePayment(amount); System.out.println(最终支付结果 (result ? 成功 : 失败)); } else { System.out.println(无效的选择); } scanner.close(); } }5. 策略模式的高级应用5.1 策略工厂模式结合在实际项目中我们通常结合工厂模式来管理策略对象的创建。// 文件路径src/main/java/strategy/factory/PaymentStrategyFactory.java package strategy.factory; import strategy.strategy.AlipayStrategy; import strategy.strategy.BankCardStrategy; import strategy.strategy.PaymentStrategy; import strategy.strategy.WechatPayStrategy; import java.util.HashMap; import java.util.Map; /** * 支付策略工厂类 */ public class PaymentStrategyFactory { public enum StrategyType { ALIPAY, WECHAT, BANK_CARD } private static MapStrategyType, PaymentStrategy strategies new HashMap(); static { strategies.put(StrategyType.ALIPAY, new AlipayStrategy(default_alipay_account)); strategies.put(StrategyType.WECHAT, new WechatPayStrategy(default_wechat_openid)); strategies.put(StrategyType.BANK_CARD, new BankCardStrategy(default_card_number, 默认银行)); } public static PaymentStrategy getStrategy(StrategyType type) { PaymentStrategy strategy strategies.get(type); if (strategy null) { throw new IllegalArgumentException(不支持的策略类型 type); } return strategy; } // 支持自定义参数的策略创建 public static PaymentStrategy createAlipayStrategy(String accountId) { return new AlipayStrategy(accountId); } public static PaymentStrategy createWechatStrategy(String openId) { return new WechatPayStrategy(openId); } public static PaymentStrategy createBankCardStrategy(String cardNumber, String bankName) { return new BankCardStrategy(cardNumber, bankName); } }5.2 Spring框架中的策略模式在Spring项目中我们可以利用依赖注入来优雅地实现策略模式。// 策略接口 public interface NotificationStrategy { void sendNotification(String message, String target); boolean supports(NotificationType type); } // 具体策略实现 - 邮件通知 Component public class EmailNotificationStrategy implements NotificationStrategy { Override public void sendNotification(String message, String email) { // 发送邮件逻辑 System.out.println(发送邮件到 email message); } Override public boolean supports(NotificationType type) { return type NotificationType.EMAIL; } } // 具体策略实现 - 短信通知 Component public class SmsNotificationStrategy implements NotificationStrategy { Override public void sendNotification(String message, String phone) { // 发送短信逻辑 System.out.println(发送短信到 phone message); } Override public boolean supports(NotificationType type) { return type NotificationType.SMS; } } // 策略上下文管理 Service public class NotificationContext { Autowired private ListNotificationStrategy strategies; public void sendNotification(NotificationType type, String message, String target) { NotificationStrategy strategy strategies.stream() .filter(s - s.supports(type)) .findFirst() .orElseThrow(() - new IllegalArgumentException(不支持的通知类型 type)); strategy.sendNotification(message, target); } }5.3 策略模式与Lambda表达式在Java 8中我们可以使用Lambda表达式让策略模式更加简洁。// 函数式策略接口 FunctionalInterface public interface ValidationStrategy { boolean validate(String input); } // 使用Lambda表达式创建策略 public class LambdaStrategyDemo { public static void main(String[] args) { // 传统的策略模式实现 ValidationStrategy lengthStrategy new ValidationStrategy() { Override public boolean validate(String input) { return input ! null input.length() 6; } }; // 使用Lambda表达式简化 ValidationStrategy lengthStrategyLambda input - input ! null input.length() 6; ValidationStrategy numericStrategy input - input ! null input.matches(\\d); ValidationStrategy emailStrategy input - input ! null input.matches(^[\\w.-][\\w.-]\\.[a-z]{2,}$); // 策略使用 System.out.println(长度验证 lengthStrategyLambda.validate(password)); System.out.println(数字验证 numericStrategy.validate(12345)); System.out.println(邮箱验证 emailStrategy.validate(testexample.com)); } }6. 常见问题与解决方案6.1 策略选择问题问题现象客户端需要知道所有具体策略类违反了迪米特法则。解决方案使用工厂模式或依赖注入来隐藏具体策略的创建细节。// 改进的策略工厂 public class EnhancedStrategyFactory { private static MapString, SupplierPaymentStrategy strategySuppliers new HashMap(); static { strategySuppliers.put(alipay, () - new AlipayStrategy(default_account)); strategySuppliers.put(wechat, () - new WechatPayStrategy(default_openid)); strategySuppliers.put(bank, () - new BankCardStrategy(default_card, 默认银行)); } public static PaymentStrategy createStrategy(String type, MapString, String params) { SupplierPaymentStrategy supplier strategySuppliers.get(type); if (supplier null) { throw new IllegalArgumentException(未知策略类型 type); } // 根据参数定制策略简化示例 return supplier.get(); } }6.2 策略参数传递问题问题现象不同策略需要不同的初始化参数如何统一管理解决方案使用配置对象或构建器模式。// 策略配置对象 public class StrategyConfig { private String accountId; private String openId; private String cardNumber; private String bankName; // getters and setters } // 策略构建器 public class StrategyBuilder { public static PaymentStrategy buildAlipayStrategy(StrategyConfig config) { return new AlipayStrategy(config.getAccountId()); } public static PaymentStrategy buildWechatStrategy(StrategyConfig config) { return new WechatPayStrategy(config.getOpenId()); } public static PaymentStrategy buildBankCardStrategy(StrategyConfig config) { return new BankCardStrategy(config.getCardNumber(), config.getBankName()); } }6.3 策略模式性能考量问题现象频繁创建策略对象可能导致性能问题。解决方案使用对象池或缓存策略对象。// 带缓存的策略工厂 public class CachedStrategyFactory { private static MapString, PaymentStrategy strategyCache new HashMap(); public static PaymentStrategy getStrategy(String type, String key) { String cacheKey type : key; return strategyCache.computeIfAbsent(cacheKey, k - createNewStrategy(type, key)); } private static PaymentStrategy createNewStrategy(String type, String key) { switch (type) { case alipay: return new AlipayStrategy(key); case wechat: return new WechatPayStrategy(key); case bank: return new BankCardStrategy(key, 缓存银行); default: throw new IllegalArgumentException(不支持的策略类型); } } }7. 策略模式的最佳实践7.1 设计原则遵守策略模式完美体现了多个面向对象设计原则开闭原则新增策略无需修改现有代码单一职责原则每个策略类只负责一个算法实现依赖倒置原则客户端依赖抽象接口而非具体实现接口隔离原则策略接口应该 focused 和特定7.2 项目中的实际应用场景电商平台支付系统// 复杂的支付策略管理 public class PaymentStrategyManager { private MapPaymentMethod, PaymentStrategy strategies new ConcurrentHashMap(); public void registerStrategy(PaymentMethod method, PaymentStrategy strategy) { strategies.put(method, strategy); } public boolean processPayment(Order order, PaymentMethod method) { PaymentStrategy strategy strategies.get(method); if (strategy null) { throw new UnsupportedPaymentMethodException(不支持的支付方式); } try { return strategy.pay(order.getTotalAmount()); } catch (PaymentException e) { // 统一的异常处理 log.error(支付处理失败, e); return false; } } }数据验证框架// 可扩展的验证策略体系 public class ValidationFramework { private ListValidationStrategy validators new ArrayList(); public void addValidator(ValidationStrategy validator) { validators.add(validator); } public ValidationResult validate(Object target) { ValidationResult result new ValidationResult(); for (ValidationStrategy validator : validators) { if (validator.supports(target.getClass())) { validator.validate(target, result); } } return result; } }7.3 测试策略策略模式让单元测试变得更加容易public class PaymentStrategyTest { Test public void testAlipayStrategy() { PaymentStrategy strategy new AlipayStrategy(test_account); assertTrue(strategy.pay(100.0)); assertEquals(支付宝支付, strategy.getStrategyName()); } Test public void testWechatPayStrategyWithInvalidAmount() { PaymentStrategy strategy new WechatPayStrategy(test_openid); assertFalse(strategy.pay(-50.0)); // 负数金额应该失败 } Test public void testStrategyContext() { PaymentContext context new PaymentContext(); context.setPaymentStrategy(new AlipayStrategy(test_account)); assertTrue(context.executePayment(100.0)); } }7.4 性能优化建议策略对象复用对于无状态的策略可以使用单例模式缓存策略结果对于计算密集型的策略考虑缓存计算结果异步策略执行对于IO密集型的策略使用异步执行策略懒加载对于不常用的策略延迟初始化8. 策略模式与其他模式的比较8.1 策略模式 vs 工厂模式策略模式关注行为的选择和替换工厂模式关注对象的创建和初始化结合使用工厂模式创建策略对象策略模式使用这些对象8.2 策略模式 vs 模板方法模式策略模式通过组合实现算法可变性模板方法模式通过继承实现算法框架固定、步骤可变选择依据如果算法整体结构固定使用模板方法如果算法完全可变使用策略模式8.3 策略模式 vs 状态模式策略模式客户端主动选择策略状态模式状态转换由内部条件触发本质区别策略模式是主动的状态模式是被动的通过系统学习策略模式我们掌握了如何将算法封装成独立的策略类实现运行时动态切换。这种设计不仅提高了代码的灵活性还大大增强了系统的可维护性和可测试性。在实际项目中合理运用策略模式能够有效应对需求变化降低系统复杂度。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门