我们通过一个具体的例子来解释这种设计思想:
比如在线刷题场景,有单选,多选,简答,判断等题目类型。这些类型通过参数type进行区分。后端需要根据前端传来的参数来判断是哪种题型进而选择不同的处理方法。
实现:
1.配置不同的handler:
public interface SubjectTypeHandler {
/**
* 拿到当前handler对应的枚举类
*/
SubjectInfoTypeEnum getHandlerType();
/**
* 要进行的操作,这里举个例子add,新增题目。不同题目类型继承这个接口后有不同的实现逻辑
*/
void add(SubjectInfoBo subjectInfoBO);
}
单选题handler实现举例:
/**
* @ClassName RadioTypeHandler
* @Description 单选题目handler
* @Author 86153
* @Date 2024/7/30 20:32
* @Version 1.0
**/
@Component
public class RadioTypeHandler implements SubjectTypeHandler{
@Resource
private SubjectRadioService subjectRadioService;
@Override
public SubjectInfoTypeEnum getHandlerType() {
return SubjectInfoTypeEnum.RADIO;//返回单选题枚举
}
@Override
public void add(SubjectInfoBo subjectInfoBO) {
//单选题目的插入
subjectRadioService.add();//调用单选题service的add方法
}
}
2.题目类型枚举类:
3.工厂实现:
* @ClassName SubjectTypeHandlerFactoory
* @Description subject题目类型处理工厂
* @Author 86153
* @Date 2024/7/30 19:24
* @Version 1.0
**/
@Component
public class SubjectTypeHandlerFactoory implements InitializingBean {
@Resource
List<SubjectTypeHandler> subjectTypeHandlerList;//自动装配所有handler
//工厂核心,Map<题目类型 , 对应handler>
//SubjectInfoTypeEnum是题目类型的枚举类
Map<SubjectInfoTypeEnum,SubjectTypeHandler> handlerMap = new HashMap<>();
//外部调用接口,传进来题目类型id,就能返回对应的handler
public SubjectTypeHandler getHandler(int subjectType) {
SubjectInfoTypeEnum subjectInfoTypeEnum = SubjectInfoTypeEnum.getByCode(subjectType);
return handlerMap.get(subjectInfoTypeEnum);//通过题目类型枚举拿到对应的handler
}
//实现InitializingBean接口,重写afterPropertiesSet方法初始化工厂
//@Resource属性注入已经将所有handler拿到一个list了
//getHandler拿到handler对应的枚举
//这里遍历list,将 <不同题目类型的枚举 ,对应的handler>放进map当中
@Override
public void afterPropertiesSet() throws Exception {
for (SubjectTypeHandler subjectTypeHandler : subjectTypeHandlerList) {
handlerMap.put(subjectTypeHandler.getHandlerType(),subjectTypeHandler);
}
}
}
这里再理一下工厂的实现逻辑: 首先@Resource将所有的hanler注入到工厂的list当中,然后通过InitializingBean接口进行初始化(bean生命周期:先进行依赖注入然后进行初始化),遍历list,将<接口枚举 , 接口handler>放在一个map当中。工厂对外提供getHandler方法,通过参数题目类型对应的code拿到对应的枚举,再拿到对应handler。
4.工厂调用:
SubjectTypeHandler handler =
subjectTypeHandlerFactoory.getHandler(不同题目类型的code);
handler.add(subjectInfoBo);//工厂根据code拿到对应题目的handler
通过代理 + 策略:
- 我们可以实现动态策略选择,省略大量if-else代码
- 分离策略的使用与创建逻辑(工厂封装对象创建的细节,我们只需要关注使用逻辑)
- 可拓展性:新的策略类可以轻松地添加到系统中,只需修改工厂类,而不影响客户端代码。比如后面需要添加一个画图题,我只需要增加策略类,增加枚举即可。