每天各种谈论设计模式,可是在日常写代码中,仍然是crud boy,那么我们如何使用设计模式运用在日常工作中呢。
先叙述场景,在监控告警系统中,往往需要通过多种通道向告警成员发送警报,例如:企业微信告警,手机短信告警,邮箱告警,语音告警等多种告警方式。
那么我们最初的做法是什么呢?
public interface AlertWayService {
void call(String recevier,Alert alert, String title);
}
定义一个发送告警的接口,然后通过判断是那种告警方式,选择调用哪个service实现类。
代码如下:
String alertWay = null;
if("weChat".equals(alertWay)){
//调用微信接口实现类发送微信
}else if ("sms".equals(alertWay)){
//短信
}else if("email".equals(alertWay)){
//邮箱
}else if("voice".equals(alertWay)){
//语音
}
这样的代码仿佛结构清晰,一眼看懂,但是其弊端也非常明显
1.代码拓展性不强,如果要加入一个新的通道方式,极其不方便。
2.大量的if-else语句使得代码阅读难度较高。
3.代码逻辑性不强。
4.在code-review环节容易被喷。
那么我们如何优雅的通过设计模式解决这种冗杂代码呢?
先上代码
public class AlertServiceStrategyFactory {
private static Map<String, AlertWayService> services = Maps.newConcurrentMap();
public static AlertWayService getAlertWay(String alertWay) {
return services.get(alertWay);
}
public static void register(String alertWay, AlertWayService alertWayService) {
if (Assert.StringAssert.isNotEmpty(alertWay)) {
services.put(alertWay, alertWayService);
}
}
}
这里我们使用策略工厂进行注册通道和通道接口。
通过Map进行存储通道字段和通道接口,并进行绑定。
通道接口还是那个接口
public interface AlertWayService {
void call(String recevier,Alert alert, String title);
}
关键在实现类中。
@Service
@Slf4j
public class EmailAlertWayServiceImpl implements AlertWayService, InitializingBean {
@Autowired
private InnerNoticeClient innerNoticeClient;
@Override
public void call(String recevier,Alert alert, String title) {
innerNoticeClient.callEmile(recevier, WeChatTemplate.getEmileTmpl(alert,title),alert.getStatus());
}
@Override
public void afterPropertiesSet() {
AlertServiceStrategyFactory.register(NotificationTypeEnums.EMAIL.getValue(),this);
}
}
service实现类中实现了InitializingBean接口,并在afterpropertiesSet中进行注册绑定通道和通道接口,通过register让AlertServiceStrategyFactory中的services这个map初始化了四种通道方式。
InitializingBean接口的详细使用可以参考其他优秀的博客。
当我们完成了这一系列的定义后,那么我们如何使用呢?
alertWay.forEach((k1) -> AlertServiceStrategyFactory.getAlertWay(k1).call(v,alert, titleOfTreeInfo));
这里通过遍历alertWay的方式进行获取通道,调用AlertServiceStrategyFactory中的getAlertWay方法 通过alertWay中定义的通道形式,有策略的进行调用相应的通道接口,实现了优雅的使用策略工厂模式进行有效的去除if-else。
优雅的代码往往只需要几行…