• 观察者模式:包工头的救赎


    引言

    "呼~噜~ 吱吱吱~"

    窗外边的大树上的知了声勉勉强强的盖过了包先生的呼噜声,包先生被大自然的闹钟给吵醒。

    睡了一大早的包先生,简简单单的收拾了一下自己。

    550ml的保温杯早已被20度的白开水灌满。

    "前方到达目的地附近~"

    包先生来到了工地,先是顺时针观望了一圈,后又逆时针的来了个"回首掏"。

    虽只过了20分钟,包先生的脸上早已是“大雨倾盆”。

    "哎哟喂,张三摸鱼又被抓了唉!"

    "李四你小心点啊"

    工友们敢怒不敢言。

    包先生擦了擦汗,打开了随身携带的保温杯,微抿一口,似乎有些许烫嘴。

    "唉,这日子,什么时候是个头啊!" 包先生唉声叹气,忧郁的眼神里充满了渴望。

    (本故事纯属瞎掰)

    观察者模式

    定义

    定义对象间的一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

    通用类图

    Subject 被观察者

    定义被观察者必须实现的职责,能够动态的增加、删除观察者和通知观察者。

    Observer 观察者

    观察者在接收到通知后会执行update方法,对接收到的消息进行处理。 所以它只需要实现update方法里的处理逻辑就行。

    ConcreteSubject 具体的被观察者

    定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。

    ConcreteObserver 具体的观察者

    实现自己的消息处理逻辑。

    包工头的救赎

    运用观察者模式,解放包工头。

    抽象出被观察者

    1. /**
    2. * 被观察者
    3. *
    4. * @author anlingyi
    5. * @date 2021/4/10 11:23 上午
    6. */
    7. public abstract class Observable {
    8. /**
    9. * 观察者列表
    10. */
    11. private Vector<Observer> obs = new Vector<>();
    12. /**
    13. * 添加观察者
    14. * @param observer
    15. */
    16. public void addObserver(Observer observer) {
    17. if (obs.contains(observer)) {
    18. return;
    19. }
    20. obs.add(observer);
    21. }
    22. /**
    23. * 移除观察者
    24. * @param observer
    25. */
    26. public void removeObserver(Observer observer) {
    27. obs.remove(observer);
    28. }
    29. /**
    30. * 通知观察者
    31. * @param msg
    32. */
    33. public void notifyObservers(String msg) {
    34. for (Observer observer : obs) {
    35. observer.update(this, msg);
    36. }
    37. }
    38. /**
    39. * 被观察者的名字
    40. *
    41. * @return
    42. */
    43. public abstract String getName();
    44. }

    定义被观察者对象

    搬砖工:张三

    1. /**
    2. * 被观察者:张三
    3. *
    4. * @author anlingyi
    5. * @date 2021/4/10 11:42 上午
    6. */
    7. public class ZhangSan extends Observable {
    8. @Override
    9. public String getName() {
    10. return "张三";
    11. }
    12. public void moFish() {
    13. System.out.println("摸会鱼");
    14. notifyObservers("摸鱼中...[懂得都懂]");
    15. }
    16. public void movingBricks() {
    17. System.out.println("搬会砖");
    18. notifyObservers("搬砖中...[cv大法]");
    19. }
    20. public void chat() {
    21. System.out.println("聊会天");
    22. notifyObservers("闲聊中...[不可描述]");
    23. }
    24. }

    搬砖工:李四

    1. /**
    2. * 被观察者:李四
    3. *
    4. * @author anlingyi
    5. * @date 2021/4/10 11:42 上午
    6. */
    7. public class LiSi extends Observable {
    8. @Override
    9. public String getName() {
    10. return "李四";
    11. }
    12. public void music() {
    13. System.out.println("听会歌");
    14. notifyObservers("听网抑云...[生而为人,我很抱歉]");
    15. }
    16. public void bilibili() {
    17. System.out.println("逛逛二次元");
    18. notifyObservers("逛B站...[发生肾么事了]");
    19. }
    20. public void movingBricks() {
    21. System.out.println("这道题我不会");
    22. notifyObservers("百度中...[java.lang.OutOfMemoryError: Java heap space]");
    23. }
    24. }

    抽象出观察者

    1. /**
    2. * 观察者
    3. *
    4. * @author anlingyi
    5. * @date 2021/4/10 11:20 上午
    6. */
    7. public interface Observer {
    8. void update(Observable observable, String msg);
    9. }

    定义观察者对象

    1. /**
    2. * 包工头
    3. *
    4. * @author anlingyi
    5. * @date 2021/4/10 11:37 上午
    6. */
    7. public class Foreman implements Observer {
    8. @Override
    9. public void update(Observable observable, String msg) {
    10. System.out.println("[包工头牌监控机]-" + observable.getName() + ":" + msg);
    11. }
    12. }

    到达工地

    1. public static void main(String[] args) {
    2. // 搬砖工:张三
    3. ZhangSan zhangsan = new ZhangSan();
    4. // 搬砖工:李四
    5. LiSi lisi = new LiSi();
    6. // 包工头
    7. Foreman foreman = new Foreman();
    8. // 包工头开始监控张三、李四
    9. zhangsan.addObserver(foreman);
    10. lisi.addObserver(foreman);
    11. // 张三又在摸鱼
    12. zhangsan.moFish();
    13. // 张三又在瞎聊天
    14. zhangsan.chat();
    15. // 张三终于开始搬砖了
    16. zhangsan.movingBricks();
    17. // 李四就爱逛b站
    18. lisi.bilibili();
    19. // 李四开始听小曲
    20. lisi.music();
    21. // 李四终于开始搬砖了
    22. lisi.movingBricks();
    23. }

    此时,包先生躺坐在房间里,吹着空调、吃着西瓜、逛着B站,时不时的瞟眼大屏幕:

    1. 摸会鱼
    2. [包工头牌监控机]-张三:摸鱼中...[懂得都懂]
    3. 聊会天
    4. [包工头牌监控机]-张三:闲聊中...[不可描述]
    5. 搬会砖
    6. [包工头牌监控机]-张三:搬砖中...[cv大法]
    7. 逛逛二次元
    8. [包工头牌监控机]-李四:逛B站...[发生肾么事了]
    9. 听会歌
    10. [包工头牌监控机]-李四:听网抑云...[生而为人,我很抱歉]
    11. 这道题我不会
    12. [包工头牌监控机]-李四:百度中...[java.lang.OutOfMemoryError: Java heap space]

    包先生的梦想终于实现,他也从最开始的迟到,变成了现在的早退,甚至旷工。

    而这一切的一切都被远在马尔代夫度假的大老板看在眼里。

    1. [大老板牌监控机]-包工头:晚到一点点也无所谓啦!
    2. [大老板牌监控机]-包工头:溜了溜了~
    3. [大老板牌监控机]-包工头:劳资今天不上班~

    最终,包先生得到了彻底的解放。

    观察者模式的优缺点

    优点

    • 观察者和被观察者之间是抽象耦合的,可以很方便的扩展观察者和被观察者。
    • 对于注册过的观察者,被观察者可以对其进行消息传递。

    缺点

    • 开发效率和运行效率可能并不高。
    • 多个观察者与被观察者调试起来困难。
    • 消息的通知默认是顺序执行的,一个观察者卡死,会影响整体的执行效率。

  • 相关阅读:
    智慧停车视频解决方案:如何让AI助力停车管理升级?
    【Linux】多线程_7
    【LeetCode】用队列实现栈和用栈实现队列(C语言)
    java 并行处理任务
    LeetCode 69. x 的平方根
    AndroidStudio案例——登录页面的切换
    史上最强 Java 学习路线图!
    基于Fasthttp实现的Gateway,性能媲美Nginx
    docker 安装 redis 6.0.8 cluster 实战 (3主3从) 安装篇
    【cancel请求】切换页面,对上一个页面正在pending的ajax进行取消操作
  • 原文地址:https://blog.csdn.net/m0_57042151/article/details/126927745