为了消除if-else
最近想把消息服务的几种下发方式通过策略模式整理一下,因为用的spring,直接上代码
public interface IMessageService {
/**
* 定位策略的key
*
* @return key
*/
String fetchkey();
//具体执行
void sent(String msg);
}
@Component
public class IEmailServiceImpl implements IMessageService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
EmailUtil emailUtil;
@Override
public String fetchkey() {
return "msg_handle_email";
}
@Override
public void sent(String msg) {...}
@Component
public class ISmsServiceImpl implements IMessageService {
@Autowired
SmsUtil smsUtil;
@Autowired
RedisTemplate redisTemplate;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public String fetchkey() {
return "msg_handle_sms";
}
@Override
public void sent(String msg) {...}
@Component
public class IWechatServiceImpl implements IMessageService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
AppWXUtil appWXUtil;
@Override
public String fetchkey() {
return "msg_handle_wechat";
}
@Override
public void sent(String msg) {...}
@Component
public class MessageHandler implements InitializingBean, ApplicationContextAware {
private Map<String, IMessageService> messageServiceMap = new ConcurrentHashMap<>(8);
private ApplicationContext applicationContext;
/**
* 将IMessageService的类都按照定义好的规则(fetchKey),放入messageServiceMap中
*/
@Override
public void afterPropertiesSet() {
Map<String, IMessageService> matchBeans = applicationContext.getBeansOfType(IMessageService.class);
matchBeans.forEach((key, value) -> messageServiceMap.put(value.fetchkey(), value));
}
/**
* 注入applicationContext
*
* @param applicationContext ac
* @throws BeansException e
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 通过key获取对应的策略实现
*
* @param key key
* @return IMessageService
*/
public IMessageService getMessageSender(String key) {
return messageServiceMap.get(key);
}
将来如果需要扩展起来也非常容易:只需在impl目录下添加策略类,定义好对应的策略key,就可以了
关键在于 MessageHandler,它实现了InitializingBean和ApplicationContextAware两个接口。
**实现了ApplicationContextAware接口的类,可以注入applicationContext实例**
实现了ApplicationContextAware接口的类,会重写方法, 可以通过此方法,让当前类拿到applicationContext实例。
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
或者通过注解获取;
@Autowired
private ApplicationContext applicationContext;
实现了InitializingBean的类,会在实例化Bean的时候,调用其afterPropertiesSet方法。
在实例化此Bean的时候,我们调用了afterPropertiesSet方法,方法里通过applicationContext对象,拿到所有IMessageService类型的类。然后将每个策略类fetchKey结果作为key,策略类本身作为value,存储到变量messageServiceMap中了。然后当要使用的时候,直接调用getMessageSender方法,根据key来获取策略类。