在复杂场景使用策略和工厂模式代替分支语句

在复杂场景使用策略和工厂模式代替分支语句

在软件开发过程中,随着业务逻辑的不断复杂,大量的分支语句往往会让代码变得臃肿、难以维护。而策略模式和工厂模式为我们提供了一种优雅的替代方案,能够有效地提升代码的可扩展性和可维护性。在复杂场景下,使用策略和工厂模式代替分支语句可以带来诸多好处。

在这里插入图片描述

直接上效果图

如果代码有几十个if-else是不是会很崩溃,但是使用策略工厂就能把if-else直接给优化掉。
在这里插入图片描述
工厂模式能够与众多其他设计模式相互融合,共同用于系统设计。例如策略工厂,其作用在于创建策略对象;还有代理工厂,专门用于创建代理对象。以 Spring 的 AOP 代理工厂为例,它会依据目标对象的具体状况,创建 JDK 代理或者 CGLIB 代理。

策略工厂实现 - 支付案例

我是如何把上面的if-else优化掉的呢。仔细看完代码就会恍然大悟,相信我一定不会后悔。

一、定义策略接口

public interface PaymentStrategy {
    /**
     * 判断条件是否为true
     */
    boolean isSupport(String payMethod);

    /**
     * 支付方法
     */
    void pay(double amount);
}

二、实现对应的策略类

// 支付宝支付
public class AlipayPaymentStrategy implements PaymentStrategy {
    @Override
    public boolean isSupport(String payMethod) {
        return "AlipayPay".equals(payMethod);
    }

    @Override
    public void pay(double amount) {
        System.out.println("使用支付宝支付:" + amount + "元。");
    }
}

// paypal支付
public class PayPalPaymentStrategy implements PaymentStrategy {

    @Override
    public boolean isSupport(String payMethod) {
        return "PayPalPay".equals(payMethod);
    }

    @Override
    public void pay(double amount) {
        System.out.println("使用 PayPal 支付:" + amount + "元。");
    }
}

// 银联支付
public class UnionPayPaymentStrategy implements PaymentStrategy {
    @Override
    public boolean isSupport(String payMethod) {
        return "UnionPay".equals(payMethod);
    }

    @Override
    public void pay(double amount) {
        System.out.println("使用银联支付:" + amount + "元。");
    }
}


// 微信支付
public class WeChatPaymentStrategy implements PaymentStrategy {
    @Override
    public boolean isSupport(String payMethod) {
        return "WeChatPay".equals(payMethod);
    }

    @Override
    public void pay(double amount) {
        System.out.println("使用微信支付:" + amount + "元。");
    }
}

三、定义策略工厂

public class PaymentFactory {

    private final List<PaymentStrategy> paymentStrategyList = new ArrayList<>();

    private static final PaymentFactory factory = new PaymentFactory();

    /**
     * 单例工厂
     */
    public static PaymentFactory getInstance() {
        return factory;
    }

    private PaymentFactory() {
        // 注册策略
        paymentStrategyList.add(new AlipayPaymentStrategy());
        paymentStrategyList.add(new WeChatPaymentStrategy());
        paymentStrategyList.add(new UnionPayPaymentStrategy());
        paymentStrategyList.add(new PayPalPaymentStrategy());
        // 后续有策略,继续添加。也可以使用类扫描或者其他方式添加
    }

    /**
     * 从注册的策略列表中获取策略
     */
    public PaymentStrategy getStrategy(String payMethod) {
        for (PaymentStrategy paymentStrategy : paymentStrategyList) {
            if (paymentStrategy.isSupport(payMethod)) {
                return paymentStrategy;
            }
        }
        new Exception("支付方式不支持");
        return null;
    }
}

四、使用

   
   // 修改之后的使用方式
   public void strategyPay(double amount, String payMethod) {
        PaymentFactory paymentFactory = PaymentFactory.getInstance();
        PaymentStrategy strategy = paymentFactory.getStrategy(payMethod);
        strategy.pay(amount);
    }


    // 修改之前的使用方式
    public void pay(double amount, String payMethod) {
        if ("AlipayPay".equals(payMethod)) {
            System.out.println("使用支付宝支付:" + amount + "元。");
        } else if ("PayPalPay".equals(payMethod)) {
            System.out.println("使用 PayPal 支付:" + amount + "元。");
        } else if ("UnionPay".equals(payMethod)) {
            System.out.println("使用银联支付:" + amount + "元。");
        } else if ("WeChatPay".equals(payMethod)) {
            System.out.println("使用微信支付:" + amount + "元。");
        } else {
            new Exception("支付方式不支持");
        }
    }

五、接口测试

    @Test
    public void testStrategyPay() {
        paymentService.strategyPay(100.0, "AlipayPay");
        paymentService.strategyPay(100.0, "PayPalPay");
        paymentService.strategyPay(100.0, "UnionPay");
        paymentService.strategyPay(100.0, "WeChatPay");
    }

结果如下

使用支付宝支付:100.0元。
使用 PayPal 支付:100.0元。
使用银联支付:100.0元。
使用微信支付:100.0元。

if-else 真的消失了吗?

表面上看,if-else 似乎消失了,但实际上它只是转移到了策略类中。策略类通常包含两个方法,一个方法对应着条件的判断,另一个方法对应着满足条件后的行为。

工厂模式在一定程度上看似消灭了 if 判断,它通过将对象的创建职责委托给工厂类,根据不同的条件返回不同的对象实例,从而避免了在使用对象的地方出现大量的 if-else 判断。

而策略模式则可以被认为消灭了条件体。策略模式将不同的算法或行为封装在不同的策略类中,通过选择不同的策略类来实现不同的行为,而不是通过传统的 if-else 条件体来决定执行哪种行为。

然而,虽然 if-else 在代码中的表现形式可能发生了变化,但实际上条件判断的逻辑并没有真正消失,只是被转移到了不同的地方进行处理。在设计软件系统时,我们可以根据具体情况选择合适的设计模式来优化代码结构,减少 if-else 的使用,但不能完全消除条件判断的本质。

在这里插入图片描述

Spring是如何使用工厂模式和策略模式的

1. BeanFactory 和 ApplicationContext 的实现

工厂模式的应用

在 Spring 中,BeanFactoryApplicationContext 是两个核心接口,用于管理和配置 Spring 应用中的 Beans。这两个接口都是工厂模式的实现,负责创建和管理 Bean 的实例。通过 BeanFactoryApplicationContext,我们可以获取任何已配置的 Bean,而这些 Bean 的实例化是由 Spring 自动处理的。

  • BeanFactory:这是一个基础的容器,提供了基本的 Bean 管理功能。通过 getBean() 方法,可以根据 Bean 的名称或类型获取 Bean 的实例。这种实例化过程由 BeanFactory 负责,Bean 的创建、销毁等生命周期管理都由它完成。
  • ApplicationContext:这是 BeanFactory 的扩展,提供了更多高级功能,例如事件发布、国际化支持和对 AOP 的集成。ApplicationContext 实际上是工厂模式的扩展和更高级别的实现,它不仅能够创建和管理 Bean,还可以根据上下文来进行更复杂的配置和管理。
策略模式的应用

Spring 中的策略模式通常体现在以下几个方面:

  • @Qualifier 注解:当一个接口有多个实现类时,Spring 使用 @Qualifier 注解来指定注入哪一个具体的实现。这就是策略模式的体现,@Qualifier 允许我们选择不同的实现策略。

    @Autowired
    @Qualifier("myServiceImpl")
    private MyService myService;
    

    通过 @Qualifier,我们可以选择注入 MyService 接口的哪一个具体实现类,从而实现不同的业务逻辑。

  • Condition 接口:Spring 允许根据条件来加载或不加载某个 Bean,这也是策略模式的一种表现。通过实现 Condition 接口,开发者可以定义在某些条件下才加载某个 Bean 的策略。

    @Bean
    @Conditional(MyCondition.class)
    public MyService myService() {
            return new MyServiceImpl();
       }
    

2. Transaction Management 的实现

工厂模式的应用

Spring 的事务管理依赖于 PlatformTransactionManager 接口。这个接口有多个实现类,比如 DataSourceTransactionManagerJpaTransactionManager 等。Spring 使用工厂模式通过配置来选择和实例化具体的事务管理器。

  • 事务管理器的选择:开发者可以在配置文件中或使用 Java 配置类来指定事务管理器的类型。Spring 会根据配置选择合适的事务管理器并将其实例化。

    
    
    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
    

    在这个例子中,JpaTransactionManager 是通过工厂方法创建的,这个过程由 Spring 管理,开发者无需手动实例化事务管理器。

策略模式的应用

Spring 事务管理框架中的策略模式体现在以下几个方面:

  • 事务传播行为:Spring 提供了多种事务传播行为(如 REQUIRED, REQUIRES_NEW, SUPPORTS 等),这些行为可以通过注解的方式指定。这些不同的传播行为实际上是不同的策略,可以根据业务需求选择合适的策略。

    @Transactional(propagation = Propagation.REQUIRED)
    public void someMethod() {
        // transactional code here
     }    
    

    这里的 Propagation.REQUIRED 就是策略模式的应用,Spring 会根据这个策略来决定如何处理事务的传播。

  • 事务隔离级别:类似地,Spring 也提供了多种事务隔离级别(如 READ_COMMITTED, REPEATABLE_READ 等),开发者可以选择不同的隔离级别策略来处理并发事务的影响。

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void anotherMethod() {
        // transactional code here
    }
    

通过这些例子,可以看到 Spring 是如何结合使用工厂模式和策略模式来实现灵活、可配置的 Bean 管理和事务管理功能的。这种设计使得 Spring Framework 具有高度的可扩展性和灵活性,能够适应不同的应用需求。

策略工厂 - 总结

当面对复杂场景时,大量的分支语句会让代码变得难以维护和理解。本文以支付案例为例,展示了如果代码中存在几十个if-else语句会带来的困扰。

通过引入策略和工厂模式,成功地将这些繁琐的if-else优化掉。在支付案例中,原本可能令人崩溃的条件判断被策略工厂巧妙替代,极大地提高了代码的可维护性和可读性。

仔细研究代码可以发现,策略模式将不同的支付方式封装成独立的策略类,而工厂模式则负责根据特定条件创建相应的策略对象。这种组合使得代码结构更加清晰,易于扩展和修改。

总之,在复杂场景下,策略和工厂模式为我们提供了一种有效的解决方案,帮助我们摆脱分支语句的困扰,提升软件的质量和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值