策略模式+反射/spring容器 代替if-else或switch-case

文章介绍了如何通过策略模式结合工厂模式和反射,以及使用Spring容器来替换冗余的if-else或switch-case结构,以提高代码的可维护性和遵循开闭原则。示例展示了支付策略的实现,包括支付宝、银行卡和微信支付,并提供了通过Spring管理策略类的另一种方法。
摘要由CSDN通过智能技术生成

策略模式代替if-else的两种方式
前言:
之前写业务逻辑的时候,发现大量的if-else处理业务逻辑,如果业务分支较少倒是还好,但是一旦后续有业务拓展的需要,一直在下面加if-else或switch-case模式,会发现,这个业务方法代码量会非常多,往往随着业务拓展,这个方法代码量都是几百行往上的飙升,最后经手的人多了,就成了大家都不愿看的屎山代码。
办法总比困难多,偶然机会发现采用策略模式来设计代码,在彻底理解里面的精髓后,才感叹设计模式的伟大之处,他的根本目的之一就是解耦合,代码的高度耦合是软件设计最忌讳的地方,因为这样会导致后续的维护性极差,策略模式+反射/Spring容器+工厂模式的组合方式,在这方面极大的优化了上面导致的问题,也很好的符合软件设计的开闭原则(对拓展开放,对修改关闭)。

方法一:策略模式+工厂模式+反射
下面2个demo案例,应该比较好理解

首先创建一个接口,抽象出公共方法放其中

下面用一个支付的案例来测试反射+策略模式的组合

公共方法的接口

package com.rao.stragry;
public interface PayStrategy {
    void pay(double total);
}

支付宝支付策略

package com.rao.stragry;

// 支付宝付款
public class Alipay implements PayStrategy {
    @Override
    public void pay(double total) {
        System.out.println("pay with alipay: " + total);
    }
}

银行卡支付策略

package com.rao.stragry;

// 银行卡付款
public class EbankPay implements PayStrategy {
    @Override
    public void pay(double total) {
        System.out.println("pay with ebankpay: " + total);
    }
}

微信支付策略

package com.rao.stragry;

//微信付款
public class WechatPay implements PayStrategy {
    @Override
    public void pay(double total) {
        System.out.println("pay with wechatpay: " + total);
    }
}

一个策略工厂

package com.rao.stragry;

public class StrategyFactory {
    public static PayStrategy getStrategy(String strategyType) throws Exception {
        String className = PayEnum.valueOf(strategyType).getClassName();
        return (PayStrategy) Class.forName(className).newInstance();
    }
}

枚举类

package com.rao.stragry;

public enum  PayEnum {

    ALIPAY("com.rao.stragry.Alipay"),
    WECHATPAY("com.rao.stragry.WechatPay"),
    EBANKPAY("com.rao.stragry.EbankPay");

    PayEnum(String className) {
        this.setClassName(className);
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    private String className;
}

测试类

package com.rao.stragry;
public class Client {
    public static void main(String[] args) throws Exception {

        String alipay = "ALIPAY";//
        PayStrategy alipay_strategy = StrategyFactory.getStrategy(alipay);
        alipay_strategy.pay(12);

        String wechatpay = "WECHATPAY";//
        PayStrategy wechatpay_strategy = StrategyFactory.getStrategy(wechatpay);
        wechatpay_strategy.pay(12);

        String ebankpay = "EBANKPAY";//
        PayStrategy ebankpay_strategy = StrategyFactory.getStrategy(ebankpay);
        ebankpay_strategy.pay(12);
    }
}

第二种方式
通过Spring提供的容器来管理,把我们的实现策略类作为一个bean,用@Component注入spring容器,通过spring容易统一来管理我们bean的生命周期,其实大体上跟上面方法一反射实现差不多,因为spring容器也是通过反射的方式去动态获取bean对象的,返回给我们一个代理对象,只不过通过spring提供的容器,我们就不需要用原始的反射方式了。这样方式也很简单,代码设计思想最重要~

下面用一个小例子演示

提取的公共方法接口

package com.rao.stragry2;
public interface PromotionStrategy {
    /**
     * 促销接口
     * @param promotionType
     */
    void doPromotion(String promotionType);
}

策略实现类一

package com.rao.stragry2;
import org.springframework.stereotype.Component;

@Component
public class DefaultStrategy implements PromotionStrategy{
    @Override
    public void doPromotion(String promotionType) {
        System.out.println("result is:"+promotionType+ "   不做促销~");
    }
}

策略实现类二

package com.rao.stragry2;
import org.springframework.stereotype.Component;

@Component
public class DisCountStrategy implements PromotionStrategy{
    @Override
    public void doPromotion(String promotionType) {
        System.out.println("result is:"+promotionType+ "   折扣策略~");
    }
}

策略实现类三

package com.rao.stragry2;
import org.springframework.stereotype.Component;
@Component
public class FeeStrategy implements PromotionStrategy{
    @Override
    public void doPromotion(String promotionType) {
        System.out.println("result is:"+promotionType+ "   0元购~");
    }
}

业务方法

package com.rao.stragry2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PromotionService {
    @Autowired
    private PromotionStrategyService promotionStrategyService;


    public void doPromotion(String promotionType){
        //获取策略实例并执行
        promotionStrategyService.getStrategyInstance(promotionType).doPromotion(promotionType);
    }
}

动态获取bean

package com.rao.stragry2;

import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Service
public class PromotionStrategyService  extends ApplicationObjectSupport {


    private final PromotionStrategy DEFAULT_PROMOTION=new DefaultStrategy();


    public PromotionStrategy getStrategyInstance(String promotionType){
        EnumPromotionType enumPromotionType=EnumPromotionType.find(promotionType);
        //枚举为空,则为默认的促销策略
        if(Objects.isNull(enumPromotionType)){
            return DEFAULT_PROMOTION;
        }
        //实际的促销策略
        return super.getApplicationContext().getBean(enumPromotionType.getDescription(),PromotionStrategy.class);
    }
}

枚举类

package com.rao.stragry2;
import lombok.Data;
import lombok.Getter;
import java.util.Arrays;
@Getter
public enum EnumPromotionType {
    /**
     * 满减
     */
    FULL_REDUCTION("1","defaultStrategy"),
    FREE("2","feeStrategy"),
    DISCOUNT("3","disCountStrategy");

    private String code;
    private String description;

    EnumPromotionType(String code,String description){
        this.code=code;
        this.description=description;
    }

    public static EnumPromotionType find(String code){
        EnumPromotionType enumPromotionType = Arrays.stream(EnumPromotionType.values())
                .filter(input -> input.getCode().equals(code))
                .findFirst()
                .orElse(null);
        return enumPromotionType;
    }
}

测试类

package com.rao;
import com.rao.stragry2.PromotionService;
import com.rao.stragry2.PromotionStrategyService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class JavaPracticeApplicationTests {

    @Autowired
    private PromotionService promotionService;

    @Test
    void contextLoads() {
        promotionService.doPromotion("1");
        promotionService.doPromotion("2");
        promotionService.doPromotion("3");
    }


}

总结:越来越感觉,越学到后面,发现代码的设计思想越来越重要,如果只是每天的重复敲业务代码,还不如每天抽出点时间提升自己,这样即是对自己的提升,然后这种提升效益于工作中,提升公司代码的维护性和可读性,对公司来说也是一种财富,毕竟代码首先是人读,再是机器读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值