Java设计模式——策略模式(解决满屏的if/else)

一、业务场景

项目需要对接支付系统,根据不同客户类型会有不同的支付方式,比如:支付宝、微信、银联、云闪付等等其他第三方支付平台,这个时候策略模式就大展身手了。

传统的if/else/switch 等等判断的写法太low了,代码糅合在一块,维护也不方便。

二、简单代码示例

1、实体类准备

订单信息类

package com.iot.designpattern.strategy.model;

import lombok.Data;
import lombok.experimental.Accessors;

/**
 * 订单信息
 *
 * @author Mr.Qu
 * @since 2021/5/18 10:56
 */
@Data
@Accessors(chain = true)
public class Order {
    /**
     * 金额
     */
    private int amount;

    /**
     * 支付类型
     */
    private String type;
}

返回结果类

package com.iot.designpattern.strategy.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 支付结果
 *
 * @author Mr.Qu
 * @since 2021/5/18 10:59
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PayResult {
    /**
     * 响应码
     */
    private int code;
    /**
     * 提示信息
     */
    private String msg;

    public static PayResult success(String msg) {
        return new PayResult(200, msg);
    }
}

2、定义策略接口(所有支付方式的接口),策略接口如下:

package com.iot.designpattern.strategy.service;

import com.iot.designpattern.strategy.model.Order;
import com.iot.designpattern.strategy.model.PayResult;

/**
 * 支付接口
 *
 * @author Mr.Qu
 * @since 2021/5/18 10:52
 */
public interface IPayment {

    /**
     * 支付
     *
     * @param order 订单信息
     * @return PayResult 支付结果
     */
    PayResult pay(Order order);
}

3、定义各种策略实现类

支付宝支付实现类:

package com.iot.designpattern.strategy.service.Impl;

import com.iot.designpattern.strategy.model.Order;
import com.iot.designpattern.strategy.model.PayResult;
import com.iot.designpattern.strategy.service.IPayment;
import org.springframework.stereotype.Service;

/**
 * 支付宝支付
 *
 * @author Mr.Qu
 * @since 2021/5/18 11:08
 */
@Service
public class AliPay implements IPayment {
    @Override
    public PayResult pay(Order order) {
        return new PayResult(200, "支付宝支付成功");
    }
}

微信支付实现类:

package com.iot.designpattern.strategy.service.Impl;

import com.iot.designpattern.strategy.model.Order;
import com.iot.designpattern.strategy.model.PayResult;
import com.iot.designpattern.strategy.service.IPayment;
import org.springframework.stereotype.Service;

/**
 * 微信支付
 *
 * @author Mr.Qu
 * @since 2021/5/18 10:58
 */
@Service
public class WechatPay implements IPayment {

    @Override
    public PayResult pay(Order order) {
        return new PayResult(200, "微信支付成功");
    }
}

银联支付实现类:

package com.iot.designpattern.strategy.service.Impl;

import com.iot.designpattern.strategy.model.Order;
import com.iot.designpattern.strategy.model.PayResult;
import com.iot.designpattern.strategy.service.IPayment;
import org.springframework.stereotype.Service;

/**
 * 银联支付
 *
 * @author Mr.Qu
 * @since 2021/5/18 11:10
 */
@Service
public class UnionPay implements IPayment {
    @Override
    public PayResult pay(Order order) {
        System.out.println("开始银联支付");
        return PayResult.success("银联支付成功");
    }
}

注:通过@Service注解将支付实现类注入spring工厂管理,默认bean名字是类名(开头小写)

4、使用策略

package com.iot.designpattern.strategy.controller;

import com.iot.designpattern.strategy.model.Order;
import com.iot.designpattern.strategy.model.PayResult;
import com.iot.designpattern.strategy.service.IPayment;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 支付
 *
 * @author Mr.Qu
 * @since 2021/5/18 15:30
 */
@RestController
@AllArgsConstructor
@RequestMapping("/pay/")
public class PayController {

    private final ApplicationContext applicationContext;

    /**
     * 支付API
     *
     * @param amount  金额
     * @param payType 支付类型
     * @return PayResult
     */
    @GetMapping()
    public PayResult pay(int amount, String payType) {
        Order order = new Order().setAmount(amount).setType(payType);

        //  根据【支付类型】获取对应的策略 bean
        IPayment payment = applicationContext.getBean(payType, IPayment.class);

        //  开始调用策略对应的支付业务逻辑
        return payment.pay(order);
    }
}

5、测试一下:

注:在调用的时候,注意payType中值为@Service对应的类名(开头小写),也可以自己在注解中命名name

Java设计模式——策略模式(解决满屏的if/else)_第1张图片Java设计模式——策略模式(解决满屏的if/else)_第2张图片Java设计模式——策略模式(解决满屏的if/else)_第3张图片

三、总结

使用策略模式,我们可以干掉大量的if/else,代码也更优雅,还能灵活扩展。像本文中的支付案例,后面如果有别的支付方式,我们只需要写一个新的对应支付实现类即可,无需修改现有代码。

当然,完全干掉if/else是不可能的,不能过度设计,不能为了使用设计模式而使用设计模式。

策略模式的优点:

  1. 干掉繁琐的if、switch判断逻辑;
  2. 代码优雅、可服用、可读性好;
  3. 符合开闭原则、扩展性好、便于维护;

策略模式的缺点:

  1. 策略如果很多的话,会造成策略类膨胀;
  2. 使用者必须清楚所有的策略类及其用途;

你可能感兴趣的:(设计模式,设计模式,java)