最近遇到挺多根据不同入参调用不同处理方法的场景,故引起思考,能不能别这么多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.结果输出
至此已经完成测试,大伙可根据业务需求进行改造使用,如有错漏,请指正!