文章目录
观察者模式
- 观察者模式
- 观察者模式实战
- 不使用观察者模式写法
- 观察者模式写法
观察者模式场景: 当一个行为发生时, 传递信息给另外一个用户接收做出相应的处理. 两者没有直接的耦合关联.
观察者模式实战模拟汽车摇号的结果进行通知. 创建 tutorials-21.0-0 模块. 进行汽车摇号服务的模拟
public class MinibusTargetService {
public String lottery(String uId) {
return Math.abs(uId.hashCode()) % 2 == 0 ?
"恭喜你, 编码".concat(uId).concat("在本次摇号中签") :
"很遗憾, 编码".concat(uId).concat("在本次摇号未中签");
}
}
不使用观察者模式写法
创建tutorials-21.0-1模块. 不使用观察者模式写法 创建 LotteryResult 类, 作为返回对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LotteryResult {
// 用户id
private String uId;
// 用户消息
private String msg;
// 业务时间
private Date dateTime;
}
摇号服务接口 LotteryService
public interface LotteryService {
LotteryResult doDraw(String uId);
}
摇号服务实现类
public class LotteryServiceImpl implements LotteryService {
private Logger logger = LoggerFactory.getLogger(LotteryServiceImpl.class);
private MinibusTargetService minibusTargetService = new MinibusTargetService();
@Override
public LotteryResult doDraw(String uId) {
// 摇号
String lottery = minibusTargetService.lottery(uId);
// 发短信
logger.info("给用户 {} 发送短信通知:{}", uId, lottery);
// 发送mq消息
logger.info("记录用户 {} 摇号结果 :{}", uId, lottery);
return new LotteryResult(uId, lottery, new Date());
}
}
测试类 :
public class ApiTest {
private Logger logger = LoggerFactory.getLogger(ApiTest.class);
@Test
public void test() {
LotteryService lotteryService = new LotteryServiceImpl();
LotteryResult result = lotteryService.doDraw("546452");
logger.info("测试结果: {}", JSON.toJSONString(result));
}
}
测试结果如下
10:01:40.111 [main] INFO com.thc.design.LotteryServiceImpl - 给用户 546452 发送短信通知:恭喜你, 编码546452在本次摇号中签
10:01:40.114 [main] INFO com.thc.design.LotteryServiceImpl - 记录用户 546452 摇号结果 :恭喜你, 编码546452在本次摇号中签
10:01:40.209 [main] INFO com.thc.design.ApiTest - 测试结果: {"dateTime":1648951300115,"msg":"恭喜你, 编码546452在本次摇号中签","uId":"546452"}
观察者模式写法
在观察者模式中 , 分为了事件监听, 事件处理 , 业务处理. 创建tutorials-21.0-2 模块 . 定义EventListener 接口
public interface EventListener {
void doEvent(LotteryResult result);
}
短信监听的实现类
public class MessageEventListener implements EventListener {
private Logger logger = LoggerFactory.getLogger(MessageEventListener.class);
@Override
public void doEvent(LotteryResult result) {
logger.info("给用户 {} 发送短信通知 (短信):{} ", result.getUId(), result.getMsg());
}
}
mq的实现类
public class MQEventListener implements EventListener{
private Logger logger = LoggerFactory.getLogger(MQEventListener.class);
@Override
public void doEvent(LotteryResult result) {
logger.info("记录用户 {} 摇号结果(mq) : {}", result.getUId(), result.getMsg());
}
}
创建EventManager 事件管理类
public class EventManager {
Map listeners = new HashMap();
public EventManager(Enum... operations) {
for (Enum operation : operations) {
this.listeners.put(operation, new ArrayList());
}
}
public enum EventType {
MQ, Message
}
/**
* 订阅
* @param eventType
* @param listener
*/
public void subscribe(Enum eventType, EventListener listener) {
List users = listeners.get(eventType);
users.add(listener);
}
/**
* 取消订阅
* @param eventType
* @param listener
*/
public void unSubscribe(Enum eventType, EventListener listener) {
List users = listeners.get(eventType);
users.remove(listener);
}
/**
* 通知
* @param eventType
* @param result
*/
public void notify(Enum eventType, LotteryResult result) {
List users = listeners.get(eventType);
for (EventListener listener : users) {
listener.doEvent(result);
}
}
}
定义 LotteryResult 结果
@NoArgsConstructor
@AllArgsConstructor
@Data
public class LotteryResult {
private String uId; // 用户ID
private String msg; // 摇号信息
private Date dateTime; // 业务时间
}
创建业务抽象类 LotteryService
public abstract class LotteryService {
private EventManager eventManager;
public LotteryService() {
eventManager = new EventManager(EventManager.EventType.MQ, EventManager.EventType.Message);
eventManager.subscribe(EventManager.EventType.MQ, new MQEventListener());
eventManager.subscribe(EventManager.EventType.Message, new MessageEventListener());
}
public LotteryResult draw(String uId) {
LotteryResult lotteryResult = doDraw(uId);
// 需要什么通知 就调用什么方法
eventManager.notify(EventManager.EventType.MQ, lotteryResult);
eventManager.notify(EventManager.EventType.Message, lotteryResult);
return lotteryResult;
}
protected abstract LotteryResult doDraw(String uId);
}
创建业务实现类
public class LotteryServiceImpl extends LotteryService {
private MinibusTargetService minibusTargetService = new MinibusTargetService();
@Override
protected LotteryResult doDraw(String uId) {
// 摇号
String lottery = minibusTargetService.lottery(uId);
// 结果
return new LotteryResult(uId, lottery, new Date());
}
}
测试类如下
public class ApiTest {
private Logger logger = LoggerFactory.getLogger(ApiTest.class);
@Test
public void test() {
LotteryServiceImpl lotteryService = new LotteryServiceImpl();
LotteryResult result = lotteryService.draw("2343246");
logger.info("测试结果: {}", JSON.toJSONString(result));
}
}
结果如下
10:11:29.926 [main] INFO c.t.d.event.listener.MQEventListener - 记录用户 2343246 摇号结果(mq) : 恭喜你, 编码2343246在本次摇号中签
10:11:29.929 [main] INFO c.t.d.e.l.MessageEventListener - 给用户 2343246 发送短信通知 (短信):恭喜你, 编码2343246在本次摇号中签
10:11:30.000 [main] INFO com.thc.test.ApiTest - 测试结果: {"dateTime":1648951889924,"msg":"恭喜你, 编码2343246在本次摇号中签","uId":"2343246"}