网站开发的难点,设计网站推荐设计酷站,网站建设 app开发 小程序,望都网站建设Java 设计模式之策略模式 (Strategy Pattern) 详解
策略模式#xff08;Strategy Pattern#xff09;是一种行为型设计模式#xff0c;旨在定义一系列算法#xff0c;将每个算法封装起来#xff0c;并使它们可以互相替换#xff0c;从而使得算法的变化不会影响使用算法的…Java 设计模式之策略模式 (Strategy Pattern) 详解
策略模式Strategy Pattern是一种行为型设计模式旨在定义一系列算法将每个算法封装起来并使它们可以互相替换从而使得算法的变化不会影响使用算法的客户端。策略模式的主要结构包括策略接口、具体策略类和上下文类通过将算法的选择与使用分离实现了代码的可维护性和灵活性。
更多设计模式请参考Java 中的 23 种设计模式详解
1. 策略模式的动机
在软件开发中经常遇到需要在运行时动态选择一种算法的情况。例如排序算法、支付方式、文件压缩等场景都可能需要在不同条件下选择不同的算法实现。如果在客户端代码中硬编码这些算法的选择逻辑会导致代码难以维护和扩展。策略模式通过将算法的选择和实现分离使得算法可以独立变化客户端代码可以更简洁和灵活。
2. 策略模式的结构
策略模式包含以下几部分
策略接口Strategy Interface定义所有支持的算法的公共接口。具体策略类Concrete Strategies实现策略接口定义具体的算法。上下文类Context Class使用一个具体策略对象来配置并维护对策略对象的引用。
3. 策略模式的UML类图 4. 策略模式的实现
以下是一个使用策略模式的Java示例该示例演示了如何选择不同的策略来执行操作
4.1 策略接口
// 定义策略接口
public interface Strategy {void execute();
}4.2 具体策略类
// 具体策略A
public class ConcreteStrategyA implements Strategy {Overridepublic void execute() {System.out.println(执行策略A);}
}// 具体策略B
public class ConcreteStrategyB implements Strategy {Overridepublic void execute() {System.out.println(执行策略B);}
}4.3 上下文类
// 上下文类
public class Context {private Strategy strategy;// 设置策略public void setStrategy(Strategy strategy) {this.strategy strategy;}// 执行策略public void executeStrategy() {if (strategy null) {throw new IllegalStateException(Strategy未设置);}strategy.execute();}
}4.4 客户端代码
public class StrategyPatternDemo {public static void main(String[] args) {Context context new Context();// 使用策略Acontext.setStrategy(new ConcreteStrategyA());context.executeStrategy(); // 输出: 执行策略A// 使用策略Bcontext.setStrategy(new ConcreteStrategyB());context.executeStrategy(); // 输出: 执行策略B}
}5. 策略模式的优缺点
优点
算法可以自由切换可以在不影响客户端的情况下更改算法。避免多重条件判断使用策略模式可以避免过多的if-else或switch-case语句。扩展性好增加新的策略时只需添加新的策略类即可不需要修改现有代码。
缺点
客户端必须知道所有的策略类客户端需要了解每个策略类的具体实现这增加了复杂度。增加对象数目如果策略较多会增加类的数量导致系统变得复杂。
6. 策略模式的应用场景
策略模式适用于以下场景
需要在不同情况下使用不同的算法。有许多相关类仅仅在行为上有所不同。需要避免使用复杂的条件语句来选择不同的行为。
7. 策略模式的变体
策略模式可以与其他设计模式结合使用以增强其功能。例如
组合模式Composite Pattern可以将策略模式与组合模式结合使得策略的选择更加灵活。工厂模式Factory Pattern可以使用工厂模式来创建策略对象从而实现策略的动态选择。
8. 策略模式与其他设计模式的比较
策略模式 vs. 状态模式两者结构类似但策略模式的不同策略是彼此独立的而状态模式的不同状态之间存在一定的关系。策略模式 vs. 命令模式命令模式用于封装请求将请求与执行解耦而策略模式用于封装算法将算法与使用算法的代码解耦。
9. 策略模式的实现细节与最佳实践
9.1 延迟初始化策略
在某些情况下策略的初始化可能比较耗时可以使用延迟初始化Lazy Initialization来提高性能
public class Context {private Strategy strategy;public void setStrategy(Strategy strategy) {this.strategy strategy;}public void executeStrategy() {if (strategy null) {// 延迟初始化strategy new ConcreteStrategyA();}strategy.execute();}
}9.2 使用反射动态加载策略
为了避免频繁修改代码可以通过反射动态加载策略
public class Context {private Strategy strategy;public void setStrategy(String strategyClassName) throws Exception {this.strategy (Strategy) Class.forName(strategyClassName).getDeclaredConstructor().newInstance();}public void executeStrategy() {strategy.execute();}
}9.3 使用配置文件管理策略
将策略的配置放在配置文件中便于管理和维护
# strategy.properties
strategyConcreteStrategyAimport java.io.InputStream;
import java.util.Properties;public class StrategyLoader {public static Strategy loadStrategy() throws Exception {Properties properties new Properties();try (InputStream input StrategyLoader.class.getResourceAsStream(/strategy.properties)) {properties.load(input);}String strategyClassName properties.getProperty(strategy);return (Strategy) Class.forName(strategyClassName).getDeclaredConstructor().newInstance();}
}9.4 策略模式与依赖注入
结合依赖注入框架如Spring可以更加灵活地管理策略的实例
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;Component
public class Context {private final Strategy strategy;Autowiredpublic Context(Strategy strategy) {this.strategy strategy;}public void executeStrategy() {strategy.execute();}
}10. 策略模式的实际应用案例 10.1 支付系统中的策略模式
在一个支付系统中可能有多种支付方式如信用卡支付、支付宝支付、微信支付等。通过策略模式可以根据用户选择的支付方式动态切换支付策略。
支付策略接口
public interface PaymentStrategy {void pay(double amount);
}具体支付策略类
// 信用卡支付策略
public class CreditCardPaymentStrategy implements PaymentStrategy {Overridepublic void pay(double amount) {System.out.println(使用信用卡支付 amount 元);}
}// 支付宝支付策略
public class AliPayPaymentStrategy implements PaymentStrategy {Overridepublic void pay(double amount) {System.out.println(使用支付宝支付 amount 元);}
}// 微信支付策略
public class WeChatPaymentStrategy implements PaymentStrategy {Overridepublic void pay(double amount) {System.out.println(使用微信支付 amount 元);}
}支付上下文类
public class PaymentContext {private PaymentStrategy paymentStrategy;// 设置支付策略public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy paymentStrategy;}// 执行支付public void pay(double amount) {if (paymentStrategy null) {throw new IllegalStateException(PaymentStrategy未设置);}paymentStrategy.pay(amount);}
}支付策略工厂类
为了更加优雅地创建支付策略可以使用工厂模式
public class PaymentStrategyFactory {public static PaymentStrategy getPaymentStrategy(String type) {switch (type) {case CreditCard:return new CreditCardPaymentStrategy();case AliPay:return new AliPayPaymentStrategy();case WeChat:return new WeChatPaymentStrategy();default:throw new IllegalArgumentException(未知的支付类型: type);}}
}客户端代码
public class PaymentDemo {public static void main(String[] args) {PaymentContext context new PaymentContext();// 从外部获取支付类型例如通过用户输入或配置文件String paymentType CreditCard; // 这里可以根据实际情况更改// 使用工厂创建支付策略PaymentStrategy paymentStrategy PaymentStrategyFactory.getPaymentStrategy(paymentType);// 设置支付策略context.setPaymentStrategy(paymentStrategy);// 执行支付context.pay(100.0); // 输出: 使用信用卡支付100.0元// 更改支付策略paymentType AliPay;paymentStrategy PaymentStrategyFactory.getPaymentStrategy(paymentType);context.setPaymentStrategy(paymentStrategy);context.pay(200.0); // 输出: 使用支付宝支付200.0元// 更改支付策略paymentType WeChat;paymentStrategy PaymentStrategyFactory.getPaymentStrategy(paymentType);context.setPaymentStrategy(paymentStrategy);context.pay(300.0); // 输出: 使用微信支付300.0元}
}优化的重点
工厂模式使用工厂模式来创建支付策略对象使客户端代码更简洁策略的创建和选择更灵活。空策略检查在上下文类中增加对策略是否为空的检查避免未设置策略时的运行时错误。策略类型动态获取通过从外部如用户输入或配置文件获取支付类型示例代码更加接近实际应用场景。
通过策略模式和工厂模式的结合可以实现一个灵活、可扩展且易于维护的支付系统。在实际开发中进一步结合依赖注入框架如Spring来管理策略对象可以提升代码的可测试性和可扩展性。