当我们开发一个功能,代码可能如下:
private void test() {
func1();
func2();
func3();
}
private void test() {
func1();
try {
func2();
} catch (Exception e) {
}
func3();
func4();
// func5
if (1 == 1) {
for (int i = 0; i < 5; i++) {
// todo1
// todo2
}
}
}
思考:这个功能,这个方法改动到底是不是很频繁。有个预期就行,如果没有预期,那就看实际改动次数。
还是上面那个代码,需要思考到底哪部分是核心,假设func1、func2、func3是库存校验、下单、修改库存。func4、func5是销量统计、发货
那么很容易判断出,func123才是核心逻辑,是下单的必要步骤。func45就是下单完之后的一些后续处理,甚至可能都不需要同步处理,比如发货,和下单并没有强绑定。
很容易就判断出来,这可能是一个发布订阅的逻辑,可以用观察者模式来重构,学了这么多年的设计模式,这不就能用上了么。
只讨论使用spring项目
public class OrderEvent {
private long id;
private String desc;
}
@Service
public class OrderEventListenerService {
@EventListener
public void handleForOrderSaveEvent(OrderEvent event) {
log.info("收到接单消息:{}", event);
}
}
@Service
public class OrderEventPublishService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void order() {
OrderEvent event = new OrderEvent(1, "接单");
log.info("发送接单消息:{}", event);
eventPublisher.publishEvent(event);
log.info("消息发送完毕:{}", event);
}
}
func4、func5是需要有先后顺序的,那么只需要加上@Order(num),按到num从小到大的顺序先后处理
@Service
public class OrderEventListenerService {
@Order(2)
@EventListener
public void handleForOrderSaveEvent1(OrderEvent event) {
log.info("2同步收到接单消息:{}", event);
}
@Order(1)
@EventListener
public void handleForOrderSaveEvent2(OrderEvent event) {
log.info("1同步收到接单消息:{}", event);
}
}
如果func5是发货,完全不依赖下单,订阅方就可以异步处理,使用@Async就行了。
@Service
public class OrderEventListenerService {
@Async
@EventListener
public void asyncHandleForOrderSaveEvent(OrderEvent event) {
log.info("异步收到接单消息:{}", event);
}
}
注意:使用的是默认线程池,最好改成自定义的线程池
如果func5是发货,除了C端用户下单以外,B端用户也能下单,但是B端下单代码完全是另一份,那么就需要有B端的下单消息,func5统一处理发货流程就行了
@Service
public class OrderEventListenerService {
@Async
@EventListener(classes = {OrderAEvent.class, OrderBEvent.class})
public void asyncHandleForOrderSaveEvent(Object event) {
log.info("异步收到接单消息:{}", event);
}
}