Java解耦的最佳方式-策略工厂模式
前言
在实际开发中,单独使用一种模式可能无法更完美解决问题,需要多种模式结合使用,比如发消息的时候,有多种消息类型可以支持,但是不同的消息类型有不同的处理逻辑,如果仅仅使用其中一种的话,并不能很好的解决问题,本期采用策略工厂模式给大家演示一下如何在代码中更好的解耦。
一、自定义消息处理注解?
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MessageHandler {
int messageType() default 0;
}
二、定义消息处理类
1.定义策略接口
public interface Strategy {
void system();
}
2.定义策略接口实现类
以下@MessageHandler(messageType = value)中的value值可以换成枚举类里定义的,不过要求是常量:
@Slf4j
@Service
@MessageHandler(messageType = 1)
public class MessageA implements Strategy {
@Override
public void system() {
log.info("MessageA");
}
}
@Slf4j
@Service
@MessageHandler(messageType = 2)
public class MessageB implements Strategy {
@Override
public void system() {
log.info("MessageB");
}
}
@Slf4j
@Service
@MessageHandler(messageType = 3)
public class MessageC implements Strategy {
@Override
public void system() {
log.info("MessageC");
}
}
3.定义消息类型枚举
@Getter
@AllArgsConstructor
public enum MessageTypeEnum {
MESSAGE_A(1, "MESSAGE_A"),
MESSAGE_B(2, "MESSAGE_B"),
MESSAGE_C(3, "MESSAGE_C");
private Integer code;
private String msg;
public static MessageTypeEnum getMessageTypeEnum(int code) {
for (MessageTypeEnum messageTypeEnum : MessageTypeEnum.values()) {
if (messageTypeEnum.getCode() == code) {
return messageTypeEnum;
}
}
return null;
}
}
三、创建策略的工厂类
/**
* 策略工厂类
*
* @author Songsong
* @date 2020-09-14 21:18
*/
@Service
public class StrategyFactory implements ApplicationContextAware {
private ApplicationContext applicationContext;
private ImmutableMap<Integer, Strategy> strategyMap;
private static ImmutableSet.Builder<Integer> builder = ImmutableSet.builder();
@PostConstruct
public void init() {
Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(MessageHandler.class);
Map<Integer, Strategy> map = beanMap.values().stream()
.collect(Collectors.toMap(
v -> {
MessageHandler messageHandler = v.getClass().getAnnotation(MessageHandler.class);
int messageType = messageHandler.messageType();
MessageTypeEnum messageTypeEnum = MessageTypeEnum.getMessageTypeEnum(messageType);
if (Objects.isNull(messageTypeEnum)) {
throw new IllegalArgumentException("message type error:" + messageType);
}
builder.add(messageHandler.messageType());
return messageHandler.messageType();
},
v -> (Strategy) v
));
strategyMap = ImmutableMap.<Integer, Strategy>builder().putAll(map).build();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public Strategy getStrategy(Integer templateHandler) {
return strategyMap.get(templateHandler);
}
public ImmutableMap<Integer, Strategy> getMaps() {
return strategyMap;
}
}
四、项目使用
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class StrategyTest {
@Resource
private StrategyFactory strategyFactory;
@Test
public void test() {
strategyFactory.getStrategy(MessageTypeEnum.MESSAGE_A.getCode()).system();
}
}
预期输出:MessageA,我们来看看效果:
结果符合预期,完美!!!
总结
以上就是策略工厂的使用,用于解决不同的消息类型处理不同的逻辑的业务场景,有其他类似的场景也可以使用以上方法,可以代替大量的if else、swith case等判断操作,用户代码逻辑中的解耦很实用,希望以上介绍可以帮助到你!!!