设计模式之策略模式【内附通过工厂方法+枚举实现根据参数调用不同的策略】

       最近遇到挺多根据不同入参调用不同处理方法的场景,故引起思考,能不能别这么多if else,能不能别每次添加一种实现就去加一个if,能不能看起来高大上一点点...;虽然脑子经常提示自己要多用设计模式,但由于遇到的公司都是赶着上线堆功能,所以一直很少使用,但这次我实在忍不住了,加个班来重构了部分代码..;废话不多说,咱开干吧!

一、个人理解与实现

策略模式,故名思意,就是我有多种策略,根据不同情况去使用不同策略;

具体代码实现分为5部分:

1.抽象策略:就是定义所有策略共同的方法,定义一个策略公共接口;

2.实现策略:就是实现抽象策略的方法,实现策略公共接口的具体实现类;

因为要根据入参来判断调用具体的实现策略,所以还需一个枚举类来建立参数值与实现类的对应关系;对应关系有了,还需一个通过反射来实例化具体策略实现类对象的工厂类,因此多加2步:

3.枚举类建立参数与具体策略实现类的对应关系:就是定义一个枚举类,设置对应关系,并实现一个方法通过入参来获取对应的实现类的path(用以反射生成对象);

4.反射实例化对象工厂:就是通过path反射生成不同的实现类;

5.上下文环境(调用入口);统一了调用入口,调用工厂类统一的方法,入参调用不同策略;

二、实现场景

实现场景:拿最近的一个场景来模拟吧,我要对多种不同题目进行评分,根据传过来的题目类型,调用不同的评分方法(策略);

三、具体实现

根据第一点的个人理解来操作实现:

1.定义一个抽象策略接口:

package com.zcouyang.demo;


/**
 * 题型评分策略
 */
public interface ScoreStrategy {

    /**
     * 共同的评分行为方法
     * @return
     */
    double toStart(String test);
}

2.具体的实现策略类

2.1单选题算分策略:

package com.zcouyang.demo;



/**
 * 单选题算分规则<br>
 *
 * <pre>
 * 对单选题进行算分
 * </pre>
 *
 * @author zcouyang
 */
public class ChoiceStrategy implements ScoreStrategy {

    /**
     * <pre>
     * 规则算分入口
     * 对单选题进行算分
     * </pre>
     * @param test
     */
    @Override
    public double toStart(String test) {
        System.out.println("进来了单选题算分策略:"+test);
        return 0d;
    }
}

2.2多选题算分策略:

package com.zcouyang.demo;


/**
 * 多选题算分规则<br>
 *
 * <pre>
 * 对多选题进行算分
 * </pre>
 *
 * @author zcouyang
 */
public class MultiChoiceStrategy implements ScoreStrategy {

    /**
     * <pre>
     * 规则算分入口
     * 对多选题进行算分
     * </pre>
     * @param test
     */
    @Override
    public double toStart(String test) {
        System.out.println("进来了多选题算分策略:"+test);
        return 0;
    }
}

3.枚举类建立参数与具体策略实现类的对应关系

package com.zcouyang.demo;

import cn.hutool.core.util.StrUtil;

/**
 * 评分策略枚举
 * @author zcouyang
 * @date 2022/9/06 15:45
 */
public enum ScoreEnumStrategy {

    /**
     * 单选题评分
     */
    CHOICE_SCORE("choice","com.zcouyang.demo.ChoiceStrategy"),

    /**
     * 多选题评分
     */
    MULTICHOICE_SCORE("multiChoice","com.zcouyang.demo.MultiChoiceStrategy");


    private String type;
    private String className;

    ScoreEnumStrategy() {
    }

    ScoreEnumStrategy(String type, String className) {
        this.type = type;
        this.className = className;
    }

    public static String getClassNameByType(String type) {
        String className = "";
        if (StrUtil.isBlank(type)) {
            return className;
        }

        for (ScoreEnumStrategy e : ScoreEnumStrategy.values()) {
            if (e.type.equalsIgnoreCase(type)) {
                className = e.className;
                break;
            }
        }
        return className;
    }

    public String getType() {
        return type;
    }

    public String getClassName() {
        return className;
    }
}

4.反射实例化对象工厂

package com.zcouyang.demo;

/**
 * 策略工厂反射执行
 * @author zcouyang
 * @date 2022/9/06 15:45
 */
public class StrategyFactory {

    /**
     * 使用策略工厂获取具体策略实现
     * @param type
     * @return
     */
    public static ScoreStrategy getScoreStrategy(String type) {
        try {
            return (ScoreStrategy) Class.forName(ScoreEnumStrategy.getClassNameByType(type)).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

5.上下文环境(调用入口)

package com.zcouyang.demo;

import cn.hutool.core.util.StrUtil;

/**
 * 评分策略上下文
 *
 * @author zcouyang
 * @date 2022/9/06 15:41
 */
public class ScoreContextStrategy {

    /**
     * 获取具体的策略实现
     *
     * @param test
     * @return
     */
    public static double toScore(String test) {
        ScoreStrategy scoreStrategy = StrategyFactory.getScoreStrategy(test);
        return scoreStrategy.toStart(test);
    }
}

三、运行测试

1.测试类

package com.zcouyang.demo;

public class Test {


    public static void main(String[] args) {

        //单选题策略
        ScoreContextStrategy.toScore("choice");

        //多选题策略
        ScoreContextStrategy.toScore("multiChoice");
    }
}

2.结果输出

 

至此已经完成测试,大伙可根据业务需求进行改造使用,如有错漏,请指正!

参考:Java 设计模式--策略模式,枚举+工厂方法实现 - satire - 博客园

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在 Spring Boot 中结合策略模式和枚设计支付可以按照以下步骤进行: 1. 定义支付方式的枚:创建一个枚类,用于表示不同的支付方式。例如: ```java public enum PaymentMethod { ALIPAY, WECHATPAY, BANKCARD } ``` 2. 定义策略接口和实现类:创建支付策略接口和具体的支付策略实现类。在接口中定义支付方法实现类中实现具体的支付逻辑。例如: ```java public interface PaymentStrategy { void pay(BigDecimal amount); } @Component public class AlipayStrategy implements PaymentStrategy { public void pay(BigDecimal amount) { // 实现支付宝支付逻辑 } } @Component public class WechatPayStrategy implements PaymentStrategy { public void pay(BigDecimal amount) { // 实现微信支付逻辑 } } @Component public class BankCardStrategy implements PaymentStrategy { public void pay(BigDecimal amount) { // 实现银行卡支付逻辑 } } ``` 3. 创建支付策略工厂类:创建一个支付策略工厂类,用于获取正确的支付策略对象。根据传入的支付方式枚值,返回对应的支付策略对象。例如: ```java @Component public class PaymentStrategyFactory { @Autowired private AlipayStrategy alipayStrategy; @Autowired private WechatPayStrategy wechatPayStrategy; @Autowired private BankCardStrategy bankCardStrategy; public PaymentStrategy getPaymentStrategy(PaymentMethod paymentMethod) { switch (paymentMethod) { case ALIPAY: return alipayStrategy; case WECHATPAY: return wechatPayStrategy; case BANKCARD: return bankCardStrategy; default: throw new IllegalArgumentException("Unsupported payment method: " + paymentMethod); } } } ``` 4. 在业务逻辑中使用支付策略:在需要使用支付功能的地方,通过支付策略工厂获取正确的支付策略对象,并调用支付方法进行支付。例如: ```java @Service public class PaymentService { @Autowired private PaymentStrategyFactory paymentStrategyFactory; public void processPayment(PaymentMethod paymentMethod, BigDecimal amount) { PaymentStrategy paymentStrategy = paymentStrategyFactory.getPaymentStrategy(paymentMethod); paymentStrategy.pay(amount); } } ``` 通过结合策略模式和枚设计支付,可以更加方便地管理和扩展支付方式,同时提高代码的可读性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值