目录
1. 策略模式的动机
2. 策略模式的结构
3. 策略模式的UML类图
4. 策略模式的实现
4.1 策略接口4.2 具体策略类4.3 上下文类4.4 客户端代码
5. 策略模式的优缺点
优点缺点
6. 策略模式的应用场景
7. 策略模式的变体
8. 策略模式与其他设计模式的比较
9. 策略模式的实现细节与最佳实践
9.1 延迟初始化策略9.2 使用反射动态加载策略9.3 使用配置文件管理策略9.4 策略模式与依赖注入
10. 策略模式的实际应用案例
10.1 支付系统中的策略模式支付策略接口具体支付策略类支付上下文类支付策略工厂类客户端代码优化的重点总结策略模式(Strategy Pattern)是一种行为型设计模式,旨在定义一系列算法,将每个算法封装起来,并使它们可以互相替换,从而使得算法的变化不会影响使用算法的客户端。策略模式的主要结构包括策略接口、具体策略类和上下文类,通过将算法的选择与使用分离,实现了代码的可维护性和灵活性。
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 {@Override public void execute() {System.out.println("执行策略A");}}
// 具体策略B public class ConcreteStrategyB implements Strategy {@Override public 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();
// 使用策略A context.setStrategy(new ConcreteStrategyA());context.executeStrategy(); // 输出: 执行策略A
// 使用策略B context.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 strategy=ConcreteStrategyAimport 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;
@Autowired public 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 {@Override public void pay(double amount) {System.out.println("使用信用卡支付:" + amount + "元");}}
// 支付宝支付策略public class AliPayPaymentStrategy implements PaymentStrategy {@Override public void pay(double amount) {System.out.println("使用支付宝支付:" + amount + "元");}}
// 微信支付策略public class WeChatPaymentStrategy implements PaymentStrategy {@Override public 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)来管理策略对象,可以提升代码的可测试性和可扩展性。
总结以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
您可能感兴趣的文章:Java策略模式取代if else Java设计模式之java策略模式详解详解Java策略模式Java设计模式中的策略(Strategy)模式解读Java利用Strategy模式实现堆排序Java设计模式之Strategy模式
