0
点赞
收藏
分享

微信扫一扫

【if-else分支控制的进阶方法】

双井暮色 2022-02-24 阅读 44
java

目录

1.需求

今天在公司的业务功能中做到了公司的支付模块这块,支付这块相信大家应该都有一个比较清晰的概念。这里就先分享支付的相关功能,而是接着这个功能来引出一个比较基础的知识点,代码中分支控制。

在做支付功能的时候,别的什么也不用多想。我的第一印象就是好多种类型:阿里,微信,余额,银联等等这些是国内主流的支付方式,还有很多很少用到的支付方式,如果项目种有需求,也需要我们一个个来对接。如果牵扯到国外的项目,国外的支付方式也需要对接。所以支付这块是比较复杂的,所以考虑做成一个工具类,以便在后面继续进行迭代。这些都是后话。还是先说一说今天将要分享的分支控制。

在看到有这么多的分支时,第一反应就是if-else的分支结构或者switch case的结构,如下:

2. 传统方式

 public void getPayType1(String payType, String orderId) {
      if ("0".equals(payType)) {
          //调用支付宝的支付方式
          //do something
      } else if ("1".equals(payType)) {
          //调用微信的支付方式
          //do something
      } else if ("2".equals(payType)) {
          //调用余额支付
          //do something
      } else if ("3".equals(payType)) {
          //银联支付
          //do something
      } else {
          //查询不到支付方式
     }
 }
 public void getPayType2(String payType,String orderId) {
        switch (payType) {
            case "0":
                //调用支付宝的支付方式
                //do something
                break;
            case "1":
                //调用支付宝的支付方式
                //do something
                break;
            case "2":
                //调用余额支付
                //do something
                break;
            case "3":
                //银联支付
                //do something
                break;
            default:
                //查询不到支付方式
                break;
        }
    }

这两种结构的分支控制,优点的话,也就只能说大部分的人都会想到这么去写。
缺点就非常的突出了,我们单把支付宝和微信两种支付方式拿出来的说,各种初始参数的定义,以及各种支付参数的定义,就非常的多。两种支付方式糅合在一个类中,就会显得非常的杂乱。如果在加上银联或者后面不挺的迭代近的新的支付方式。整个类的结构就是非常的混乱的,不利用后期的维护,代码的可阅读性以及可扩展性就会比较差一些。

这种的分支结构时非常的不建议大家选择的。

在上面所说的这种结构的基础上,可能我们大家就会非常容易的过渡到下面所要所要说的结构。

3. 策略模式

策略模式:
比如说对象的某个行为,在不同场景中有不同的实现方式,这样就可以将这些实现方式定义成一组策略,每个实现类对应一个策略,在不同的场景就使用不同的实现类,并且可以自由切换策略。

在网上找了张图,大家可以直观的看看:
在这里插入图片描述
然后我们再把策略模式带入到我们自己的业务中。就是把各种不同的支付方式抽取出来形成一个个的支付策略。然后再提供一个类似客户端的东西来选择不同的支付策略。这样的话,整个代码的逻辑就非常的清晰了,而且各种不同的支付方式也隔离开了,代码的可阅读性,以及后期的维护都会变得比较容易了。

/**
 * @description: 支付策略的抽象类
 * @author: WangYX
 * @create: 2022-02-24 16:18
 * @Version: 1.0.0
 **/

public abstract class Strategy {

    //不同的支付行为
    public abstract void pay(String orderId);

}
/**
 * @description: 阿里支付
 * @author: WangYX
 * @create: 2022-02-24 16:19
 * @Version: 1.0.0
 **/

public class AliPayStrategy extends Strategy {

    @Override
    public void pay(String orderId) {
        //阿里支付
    }

}
/**
 * @description: 微信支付
 * @author: WangYX
 * @create: 2022-02-24 16:19
 * @Version: 1.0.0
 **/

public class WxPayStrategy extends Strategy {

    @Override
    public void pay(String orderId) {
        //微信支付
    }

}
/**
 * @description: 余额支付
 * @author: WangYX
 * @create: 2022-02-24 16:19
 * @Version: 1.0.0
 **/

public class BalancePayStrategy extends Strategy {

    @Override
    public void pay(String orderId) {
        //余额支付
    }

}
/**
 * @description:银联支付
 * @author: WangYX
 * @create: 2022-02-24 16:19
 * @Version: 1.0.0
 **/

public class UnionPayStrategy extends Strategy {

    @Override
    public void pay(String orderId) {
        //银联支付
    }

}

策略模式统一对外提供入口:

/**
 * @description:
 * @author: WangYX
 * @create: 2022-02-24 16:27
 * @Version: 1.0.0
 **/

public class Context{

    private Strategy strategy;

    public PayClient(Strategy strategy) {
        this.strategy = strategy;
    }

    public void pay(String orderId) {
        this.strategy.pay(orderId);
    }
}

以上整个策略模式基本完成,我们接下来来看看如何进行调用。

    public void getPayType2(String payType,String orderId) {
        switch (payType) {
            case "0":
                //调用支付宝的支付方式
                new Context(new AliPayStrategy()).pay(orderId);
                break;
            case "1":
                //调用微信的支付方式
                new Context(new WxPayStrategy()).pay(orderId);
                break;
            case "2":
                //调用余额支付
                new Context(new BalancePayStrategy()).pay(orderId);
                break;
            case "3":
                //银联支付
                new Context(new UnionPayStrategy()).pay(orderId);
                break;
            default:
                //查询不到支付方式
                break;
        }
    }

以上便是整个策略模式的全部内容了,后面如果我们需要维护支付方式,只需要找到具体的类,修改类中的代码就好了。如果添加新的支付方式,只需继承Strategy类,然后把自己添加到switch的分支结构中。这个代码结构的逻辑脉络就比较清晰了。

我在项目中选用的就是这种结构。

但是,上面的方式还是存在着if-else的这中分支结构的选择。下面我们就在提供两外一种结构的选择。

4. 选择Map结构

  1. 采用Map结构
/**
 * @description:
 * @author: WangYX
 * @create: 2022-02-24 15:48
 * @Version: 1.0.0
 **/
@Service
public class Pay3Service {


    private Map<String, Strategy> payType = new HashMap<>();

    @PostConstruct
    public void init() {
        payType.put("0", new AliPayStrategy());
        payType.put("1", new WxPayStrategy());
        payType.put("2", new BalancePayStrategy());
        payType.put("3", new UnionPayStrategy());
    }

    public void getPayType2(String type,String orderId) {
        Strategy strategy = payType.get(type);
        strategy.pay(orderId);
    }

}

采用Map的数据结构就完全规避了if-else的这种分支控制。
在其中我们初始化使用了@PostConstruct这个注解,注解的作用就是在spring或者spring boot项目启动之后,初始化我们的map数据结构。

@PostConstruct注解好多人以为是Spring提供的。其实是Java自己的注解。

Java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。

通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:

Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)

  1. 另外一种Map结构
/**
 * @description:
 * @author: WangYX
 * @create: 2022-02-24 15:48
 * @Version: 1.0.0
 **/
@Service
public class Pay5Service {


    private Map<String, Consumer<String>> payType = new HashMap<>();

    @PostConstruct
    public void init() {
        payType.put("0", orderId -> new AliPayStrategy().pay(orderId));
        payType.put("1", orderId -> new WxPayStrategy().pay(orderId));
        payType.put("2", orderId -> new BalancePayStrategy().pay(orderId));
        payType.put("3", orderId -> new UnionPayStrategy().pay(orderId));
    }

    public void getPayType2(String type, String orderId) {
        Consumer<String> consumer = payType.get(type);
        if (consumer != null) {
            consumer.accept(orderId);
        }
    }

}

这种的方式,Map种的value是一种函数式接口,需要大家对函数式接口有基础的理解。

以上便是对if-else分支控制进阶方法的理解。

举报

相关推荐

0 条评论