您当前的位置: 首页 > 

java持续实践

暂无认证

  • 5浏览

    0关注

    746博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

设计模式 观察者模式

java持续实践 发布时间:2022-04-03 10:27:09 ,浏览量:5

文章目录
      • 观察者模式
      • 观察者模式实战
        • 不使用观察者模式写法
        • 观察者模式写法

观察者模式

观察者模式场景: 当一个行为发生时, 传递信息给另外一个用户接收做出相应的处理. 两者没有直接的耦合关联.

观察者模式实战

模拟汽车摇号的结果进行通知. 创建 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"}
关注
打赏
1658054974
查看更多评论
立即登录/注册

微信扫码登录

0.0540s