背景说明:
随着业务逻辑越来越多,if else也越来越长,所以就想重新优化一下,看了一下资料,写了一点伪代码,记录一下自己的体会.
场景说明:
不同的支付类型对应不同的支付类型的业务处理逻辑.
1.直接使用if else处理业务逻辑:
public static void main(String[] args) {
String payType="";
if("待支付".equals(payType)){
// 模拟待支付的业务逻辑
System.out.println("处理待支付的业务逻辑");
}
if("支付完成".equals(payType)){
// 模拟支付完成的业务逻辑
System.out.println("处理支付完成的业务逻辑");
}
if("支付失败".equals(payType)){
// 模拟支付失败的业务逻辑
System.out.println("支付失败的业务逻辑");
}
// 省略多余的if else逻辑
}
2.策略模式+工厂方法重构if else
思路描述:构建支付类型业务处理接口,不同的支付类型实现该接口并重写接口方法实现支付类型的具体处理逻辑;构建支付类型工厂,根据对应支付类型获取支付类型业务处理接口实现类.
2.1构建支付类型接口
public interface PayTypeHandleService {
// 处理指定的支付类型逻辑
void executePayType(String payTpe);
}
2.2 根据不同的支付类型实现支付类型处理接口
public class ReadyPayServiceImp implements PayTypeHandleService {
// 实现支付策略接口,实现待支付的业务逻辑
@Override
public void executePayType(String payTpe) {
System.out.println("执行待支付的业务逻辑处理");
}
}
public class SuccessPayServiceImp implements PayTypeHandleService {
// 实现支付策略接口,完成支付成功的业务逻辑
@Override
public void executePayType(String payTpe) {
System.out.println("支付成功的业务逻辑处理");
}
}
public class FailPayServiceImp implements PayTypeHandleService {
// 实现支付策略接口,模拟支付失败业务逻辑处理
@Override
public void executePayType(String payTpe) {
System.out.println("执行支付失败的业务逻辑处理");
}
}
2.3构建支付类型工厂,根据不同的支付类型获取不同的支付类型接口实现类
public class PayStrategyFactory {
// 指定的支付类型对应一种支付策略的实现类
private static Map<String,PayTypeHandleService> payTypeHandleServiceMap=new HashMap<>();
// 将存在的支付类型以及对应的处理逻辑封装到map中
static {
payTypeHandleServiceMap.put("待支付",new ReadyPayServiceImp());
payTypeHandleServiceMap.put("支付成功",new SuccessPayServiceImp());
payTypeHandleServiceMap.put("支付失败",new FailPayServiceImp());
}
// 根据不同的支付类型获取对应的支付逻辑实现类
public static PayTypeHandleService getPayHandle(String payType){
return payTypeHandleServiceMap.get(payType);
}
}
2.4使用策略模式+工厂方法进行测试
public static void main(String[] args) {
// 根据工厂模式+策略模式测试根据不同的支付类型获取不同的业务处理逻辑
PayTypeHandleService readyPayService = PayStrategyFactory.getPayHandle("待支付");
readyPayService.executePayType("待支付");
// 输出结果:执行待支付的业务逻辑处理
}
补充:1.策略模式感觉和多态差差不多,父类引用指向子类对象;2.关于构建支付类型实例,可以做成枚举类型.
策略模式:定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换;一个类的行为或其算法可以在运行时更改,简单来说就是对变化的参数运行对应的程序,我们会想到:if(…){…}else if(…){}… ,但if-else用的多了,程序可读性和维护程度就大大下降。
枚举处理参考代码:
public enum PayTypeHandleEnum {
PAYSUCCESS("支付成功",new SuccessPayServiceImp()),
PAYFALI("支付失败",new FailPayServiceImp()),
READYPAY("待支付",new ReadyPayServiceImp());
private String payType;
private PayTypeHandleService payTypeHandleService;
PayTypeHandleEnum(String payType,PayTypeHandleService payTypeHandleService){
this.payType=payType;
this.payTypeHandleService=payTypeHandleService;
}
// 根据传递的类型获取对应的实现类
public static PayTypeHandleService getPayTypeHandleService(String payType){
// 遍历枚举
PayTypeHandleEnum[] values = PayTypeHandleEnum.values();
for (PayTypeHandleEnum value : values) {
if(payType.equals(value.payType)){
return value.payTypeHandleService;
}
}
return null;
}
public static void main(String[] args) {
PayTypeHandleService successPayServiceImpl = PayTypeHandleEnum.getPayTypeHandleService("支付成功");
successPayServiceImpl.executePayType("支付成功");
}
}
3.注解方式重构if-else
实现原理:自定义注解作用于所有的支付实现类.应用初始化时组装支付容器,调用时根据支付类型获取对应的支付对象实例,执行支付逻辑.需要用到容器对象,此处使用ApplicationListener监听器,初始化或刷新时组装支付容器.
自定义注解:
@Target({
ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomerPayType {
String payType() ; // 标识支付类型
}
支付接口:
public interface PayService {
void pay();
}
三种支付实现类:
@Component
@CustomerPayType( payType = "aliPay")
public class AliPayService implements PayService {
/*阿里支付*/
@Override
public void pay() {
System.out.println("支付宝支付逻辑开始");
}
}
@Component
@CustomerPayType( payType = "applePay")
public class ApplePayService implements PayService {
/*苹果支付*/
@Override
public void pay() {
System.out.println("苹果支付逻辑开始");
}
}
@Component
@CustomerPayType( payType = "weChatPay")
public class WeChatPayService implements PayService {
/*微信支付*/
@Override
public void pay() {
System.out.println("微信支付逻辑开始");
}
}
支付处理逻辑:
@Component
public class AnnotationPayHandle implements ApplicationListener<ContextRefreshedEvent> {
private static HashMap<String,PayService> payServiceHashMap;
// ContextRefreshedEvent 容器初始化或是刷新时会触发此事件
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// 初始化自定义容器
payServiceHashMap=new HashMap<>();
// 获取容器
ApplicationContext applicationContext = event.getApplicationContext();
// 获取使用自定义注解CustomerPayType的bean对象,map中key为实例对象名,value为实例对象
Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(CustomerPayType.class);
beansWithAnnotation.forEach((key,value)->{
// 组装自定义支付容器
String payType = value.getClass().getAnnotation(CustomerPayType.class).payType();
payServiceHashMap.put(payType,(PayService)value);
});
}
// 根据支付类型执行对应的支付逻辑
public void executePayByAnnotation(String payType){
payServiceHashMap.get(payType).pay();
}
}
测试类中进行测试:
@SpringBootTest
class SecondKillApplicationTests {
@Autowired
private AnnotationPayHandle annotationPayHandle;
@Test
public void testKill(){
// 注解实现根据不同的支付类型进行对应的支付逻辑
annotationPayHandle.executePayByAnnotation("aliPay");
// 输出: 支付宝支付逻辑开始
}
}
4.根据类名获取支付实例对象执行支付逻辑重构优化ifelse
原理:直接利用applicationContext容器对象根据类名获取支付实例对象(容器加载bean到map容器中,默认beanName为首字母小写的类名),根据支付实例对象直接调用支付方法.
支付接口:
public interface PayService {
void pay();
}
支付实现类接口:
@Component
public class AliPayService implements PayService {
/*阿里支付*/
@Override
public void pay() {
System.out.println("支付宝支付逻辑开始");
}
}
@Component
public class ApplePayService implements PayService {
/*苹果支付*/
@Override
public void pay() {
System.out.println("苹果支付逻辑开始");
}
}
@Component
public class WeChatPayService implements PayService {
/*微信支付*/
@Override
public void pay() {
System.out.println("微信支付逻辑开始");
}
}
支付处理逻辑:
@Component
public class BeanNamePayHandle {
@Autowired
private ApplicationContext applicationContext;
// 从容器中直接获取支付对象实例,参数为支付实现类类名,首字母小写
public void executePayByBeanName(String payServiceName){
// 获取支付类型对象
PayService payService = (PayService) applicationContext.getBean(payServiceName);
// 执行支付方法
payService.pay();
}
}
测试实现:
@SpringBootTest
class SecondKillApplicationTests {
@Autowired
private BeanNamePayHandle beanNamePayHandle;
@Test
public void testKill(){
// 利用beanName方式执行支付逻辑
beanNamePayHandle.executePayByBeanName("applePayService");
// 输出内容:苹果支付逻辑开始
}
}