行为性模式-观察者模式
本文模拟摇号流程(1.调用外部摇号接口,2.发送摇号结果短信,3.记录摇号结果),先将1、2、3步骤在一个类中实现,后使用观察者模式将核心功能1与非核心功能2、3抽离出来实现(降低耦合、更好扩展)
外部摇号接口
public class MinBusTargetService {
public String lotter(String uId){
return Math.abs(uId.hashCode()) % 2==0 ? "恭喜.编号" + uId + "中签" : "遗憾.编号" +uId + "未中签";
}
}
普通实现
public LotterResult doDraw(String uId) {
String lotter = minBusTargetService.lotter(uId);
logger.info("记录用户 {} 抽签结果 {}", uId,lotter);
logger.info("给用户 {} 发送短信通知 {}",uId,lotter);
return new LotterResult(uId,lotter,new Date());
}
测试结果
15:50:38.058 [main] INFO c.l.design.event.listener.MqListener - 记录用户 10001 抽签结果 恭喜.编号10001中签
15:50:38.063 [main] INFO c.l.d.event.listener.MessageListener - 给用户 10001 发送短信通知 恭喜.编号10001中签
15:50:38.161 [main] INFO com.leilei.design.ApiTest - {"date":1726818638055,"msg":"恭喜.编号10001中签","uId":"10001"}
观察者模式重构实现
1.事件监听 2.事件处理 3.核心摇号业务处理
事件监听
public class MessageListener implements EventListener{
private Logger logger = LoggerFactory.getLogger(MessageListener.class);
@Override
public void doEvent(LotterResult lotterResult) {
logger.info("给用户 {} 发送短信通知 {}",lotterResult.getuId(),lotterResult.getMsg());
}
}
事件处理
public class EventManager {
private Map<Enum<EventType>, List<EventListener>> eventListenerMap = new HashMap<>();
public EventManager(Enum<EventType>... operations) {
for (Enum<EventType> eventType : operations) {
this.eventListenerMap.put(eventType,new ArrayList<EventListener>());
}
}
public enum EventType {
Message, Mq
}
public void subscribe(Enum<EventType> eventTypeEnum, EventListener eventListener) {
List<EventListener> eventListenerList = eventListenerMap.get(eventTypeEnum);
eventListenerList.add(eventListener);
}
public void unSubscribe(Enum<EventType> eventTypeEnum, EventListener eventListener) {
List<EventListener> eventListenerList = eventListenerMap.get(eventTypeEnum);
eventListenerList.remove(eventListener);
}
public void notify(Enum<EventType> eventTypeEnum, LotterResult lotterResult) {
List<EventListener> eventListenerList = eventListenerMap.get(eventTypeEnum);
for (EventListener eventListener : eventListenerList) {
eventListener.doEvent(lotterResult);
}
}
}
摇号业务处理
public abstract class LotterService {
private EventManager eventManager;
abstract LotterResult doDraw(String uId);
public LotterService() {
eventManager = new EventManager(EventManager.EventType.Mq,EventManager.EventType.Message);
eventManager.subscribe(EventManager.EventType.Mq, new MqListener());
eventManager.subscribe(EventManager.EventType.Message, new MessageListener());
}
public LotterResult draw(String uId){
LotterResult lotterResult = doDraw(uId);
eventManager.notify(EventManager.EventType.Mq,lotterResult);
eventManager.notify(EventManager.EventType.Message,lotterResult);
return lotterResult;
}
}
测试
@Test
public void test() {
LotterService lotterService = new LotterServiceImpl();
LotterResult result = lotterService.draw("10001");
logger.info(JSON.toJSONString(result));
}
测试结果
15:49:50.099 [main] INFO c.l.design.event.listener.MqListener - 记录用户 10001 抽签结果 恭喜.编号10001中签
15:49:50.104 [main] INFO c.l.d.event.listener.MessageListener - 给用户 10001 发送短信通知 恭喜.编号10001中签
15:49:50.222 [main] INFO com.leilei.design.ApiTest - {"date":1726818590095,"msg":"恭喜.编号10001中签","uId":"10001"}