记一次设计模式随笔
1. 有一个公共的代码处理逻辑
1 private void linkReceipt(LinkSendNotifyDTO linkSendNotifyDTO) { 2 if (linkSendNotifyDTO.getStatus() != null && linkSendNotifyDTO.getStatus()) { 3 //==================1、处理业务类型定制化业务================== 4 BizHandler bizHandler = BizHandlerFactory.getInstance(linkSendNotifyDTO.getChannelBizType()); 5 bizHandler.doReceipt(linkSendNotifyDTO.getOrderId(), linkSendNotifyDTO.getData()); 6 7 //==================2、处理某些渠道定制化业务================== 8 ChannelHandler channelHandler = ChannelHandlerFactory.getInstance(linkSendNotifyDTO.getNodeMapping()); 9 channelHandler.doReceipt(linkSendNotifyDTO); 10 } 11 12 //==================3、处理公共逻辑================== 13 Integer status = null; 14 Integer recordStatus = null; 15 if (linkSendNotifyDTO.getStatus() != null && linkSendNotifyDTO.getStatus()) { 16 status = ReceiptStatus.ACCEPTED.getCode(); 17 recordStatus = DocChannelStatus.SUCCESS.getCode(); 18 19 } else { 20 status = ReceiptStatus.REFUSED.getCode(); 21 recordStatus = DocChannelStatus.FAIL.getCode(); 22 } 23 24 String channelCode = linkSendNotifyDTO.getNodeMapping(); 25 26 if (!orderLinkServiceConfig.getOrderLinkChannelCodeDocChannelRecordBlocklist().contains(channelCode)) { 27 //3.1、更新单证发送记录状态29 } 30 31 if (!orderLinkServiceConfig.getOrderLinkChannelCodeDocumentEventBlocklist().contains(channelCode)) { 32 //3.2、订单标准事件入库36 } 37 38 if (!orderLinkServiceConfig.getOrderLinkChannelCodeDingdingBlocklist().contains(channelCode)) { 39 //3.3、钉钉消息43 } 44 }
抽象的Handler,实现自定义自己的策略
//1、处理业务类型定制化业务 public abstract class BizHandler { public abstract void doReceipt(Long orderId, String bizData); } //2、处理某些渠道定制化业务 public abstract class ChannelHandler { public abstract void doReceipt(LinkSendNotifyDTO linkSendNotifyDTO); }
使用工厂方法获取策略
1 public class ChannelHandlerFactory implements ApplicationContextAware { 2 private static ApplicationContext context; 3 private static final Map<String, Class<? extends ChannelHandler>> map = new HashMap<>(); 4 5 static { 6 map.put("booking_sinko_rpa", SinkoBookingChannelHandler.class); 7 map.put("booking_sitc_rpa", SitcBookingChannelHandler.class); 8 map.put("surcharge_maersk_rpa", MaerskSurchargeChannelHandler.class); 9 } 10 11 public static ChannelHandler getInstance(String channelCode) { 12 return map.containsKey(channelCode) ? context.getBean(map.get(channelCode)) : context.getBean(DefaultChannelHandler.class); 13 } 14 15 @Override 16 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 17 context = applicationContext; 18 } 19 }
ps.具体实现的策略
1 public class SinkoBookingChannelHandler extends ChannelHandler { 2 3 @Autowired 4 private OrderRabbitMQSender orderRabbitMQSender; 5 private static String SINKO_EMAIL_EXCHANGE = "SinkoEmailExchange"; 6 7 @Override 8 public void doReceipt(LinkSendNotifyDTO linkSendNotifyDTO) { 9 String bizData=linkSendNotifyDTO.getData(); 10 Long orderId=linkSendNotifyDTO.getOrderId(); 11 if (StringUtils.isBlank(bizData)) return; 12 BookingResultVO data = JSONObject.parseObject(bizData, BookingResultVO.class); 13 String bookingNumber = StringUtil.removeNotLetterNumber(data.getBookingNo()); 14 if (StringUtils.isBlank(bookingNumber)) return; 15 OrderReceiptDTO orderReceiptDTO = OrderReceiptDTO.builder() 16 .orderId(orderId) 17 .bookingNumber(StringUtils.replaceAll(bookingNumber, "[^a-zA-Z0-9]", "")) 18 .build(); 19 String json = JSONObject.toJSONString(orderReceiptDTO); 20 YQNExecutor.execute(new YQNRunnable() { 21 @Override 22 public void runBiz() { 23 orderRabbitMQSender.send(SINKO_EMAIL_EXCHANGE, "", json); 24 Loggers.BIZ.info("LinkMQReceiptConsumer-长锦订舱成功,发送邮件" + orderId + "json:" + json); 25 } 26 }); 27 } 28 }
问题1:自定义策略被一个if条件包裹,但是有些策略执行条件不一样
问题2:有个别策略在公共逻辑处理上有点小不同,不想使用if else做特殊处理
问题3:不想使用多个黑名单的方式过滤策略使用公共逻辑
==》使用模板方法
1 public abstract class ChannelTemplateHandler { 2 //自定义校过滤 3 public boolean before(Boolean status) { 4 return status == null ? false : status; 5 } 6 7 public abstract void doReceipt(LinkSendNotifyDTO linkSendNotifyDTO); 8 9 public void after(LinkSendNotifyDTO linkSendNotifyDTO) { 10 this.updateDocChannelRecordStatus(linkSendNotifyDTO); 11 this.saveDocumentEvent(linkSendNotifyDTO); 12 this.sendDingdingReminderNew(linkSendNotifyDTO); 13 } 14 15 //更新单证发送记录状态 16 public void updateDocChannelRecordStatus(LinkSendNotifyDTO linkSendNotifyDTO) { 17 //do something 18 } 19 20 //订单标准事件入库 21 public void saveDocumentEvent(LinkSendNotifyDTO linkSendNotifyDTO) { 22 //do something 23 } 24 25 //钉钉消息 26 public void sendDingdingReminderNew(LinkSendNotifyDTO linkSendNotifyDTO) { 27 //do something 28 } 29 }