只有我有写过使用策略模式+工厂模式的形式,其中工厂模式负责策略的分发。但是有个问题就是工厂模式中依然避免不了通过if else来判断需要返回哪种策略,下面就通过自定义注解的形式来实现策略模式的分发。
1.定义策略的枚举类
public enum ProcessTypeEnum {
CHAT_MSG,
SYS_MSG;
}
2.定义一个注解来表示策略是哪种类型
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Type {
ProcessTypeEnum value();
}
3.定义策略类的顶层接口
public interface ProcessStrategy {
/**
* 处理消息
* @param content
* @return
*/
String handleMsg(String content);
}
4.定义具体的策略类
@Slf4j
@Component
@Type(ProcessTypeEnum.CHAT_MSG)
public class ChatProcessStrategy implements ProcessStrategy {
@Override
public String handleMsg(String content) {
return "Chat msg:" + content;
}
}
@Slf4j
@Component
@Type(ProcessTypeEnum.SYS_MSG)
public class SysProcessStrategy implements ProcessStrategy {
@Override
public String handleMsg(String content) {
return "sys msg:" + content;
}
}
5.实现分发的逻辑
@Component
public class MsgConfig implements ApplicationContextAware {
public static final Map<ProcessTypeEnum, ProcessStrategy> container = new HashMap<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
applicationContext.getBeansWithAnnotation(Type.class).entrySet().iterator().forEachRemaining(entrySet ->
container.put(entrySet.getValue().getClass().getAnnotation(Type.class).value(), (ProcessStrategy)entrySet.getValue()));
}
}
6.实际调用
@Data
public class MsgContent {
private ProcessTypeEnum processType;
private String content;
}
@RestController
public class StrategyController {
@PostMapping("strategy")
public ResponseEntity<String> strategy(@RequestBody MsgContent msgContent){
String s = MsgConfig.container.get(msgContent.getProcessType()).handleMsg(msgContent.getContent());
return ResponseEntity.ok(s);
}
}
通过注解的形式来实现策略模式的好处就是当我们需要新添加一个策略时,直接加一个具体的策略类,然后在枚举类里面添加一个枚举就可以了,比工厂模式要更加便捷。设计模式中对修改关闭,增加开放的原则。