Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 285|回复: 0

[设计模式学习]观察者模式与QQ的好友登录机制

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-1 00:00:02 | 显示全部楼层 |阅读模式
    观察者模式(Observer):定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。 适用场景: 1、当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用; 2、当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变; 3、当一个对象必须通知其它对象,而它又不能假定其它对象是谁,即这些对象是松耦合的。 通用类图:

        当我学习 Observer 模式时,我根据其特点将其映射到一个很常见的场景中,即 QQ 登录。当我登录自己的QQ时,一般情况下我的所有好友都会在主面板上高亮我的头像,表示我上线了。这样的一种机制,和上面 Observer 模式的定义很相似,我与许多好友之间明显是一对多的依赖关系,当我登录时,好友们的QQ面板中我的头像的状态也发生改变了(由暗黑到高亮),而好友们之所以会得知我登录了,就是由类似于 Observer 模式来实现的,即被通知并自动更新。实际上,我认为QQ的这种机制应该是运用了数据库中的触发器机制。 基于上面的例子,我就是被观察者 Subject 主题类,而我的好友们就是观察者 Observer 类,相关方法先看类图,下面再回过头来看看。那么再来相应地分析一下 Observer 模式的适用场景: 1、我和我的许多好友有互相依赖的关系,我可以被任何一位通过我的确认的QQ号码添加为好友,此时好友依赖于我,但是我们之间仍然可以独立封装、独立存在,即就算没有某一位特定的QQ号码添加我为好友时,我还是一位QQ用户。嗯,说得有点杂了,不过应该能理解的; 2、当然,我登录时没必要清楚地知道我有多少好友,QQ服务器尽量通知我的那些应该被通知的好友即可; 3、最后一点,不知道匹配得恰不恰当…当我的某个好友设置了“在线对其隐身”时,那么即使我上线了该好友也不会被通知。在这里,我的设置是事先完成的了,当我上线时,当然也没必要去了解谁被我设置了权限。此时,我和这位特殊的好友是松耦合的。 说了那么多,快点用代码来实现一下(方法名与通用类图中的有所差异):
    1. /**
    2. *  抽象的观察者,具有update()方法,
    3. *  能够将接收到的信息进行逻辑处理,
    4. *  可以是 interface ,不一定是抽象类
    5. */
    6. abstract class Observer {
    7.         public abstract void update(String name);
    8. }
    9. // 具体观察者01,即QQ好友-01
    10. class Observer01 extends Observer {
    11.         public void update(String name) {
    12.                 System.out.println("QQ好友-01 得知 " + name + "上线了");
    13.         }
    14. }

    15. // 具体观察者02,即QQ好友-02
    16. class Observer02 extends Observer {
    17.         public void update(String name) {
    18.                 System.out.println("QQ好友-02 得知 " + name + "上线了");
    19.         }
    20. }

    21. // 具体观察者03,即QQ好友-03
    22. class Observer03 extends Observer {
    23.         public void update(String name) {
    24.                 System.out.println("QQ好友-03 得知 " + name + "上线了");
    25.         }
    26. }

    27. // 抽象的被观察者,是所有Observer的观察抽象主题
    28. abstract class AbstractSubject {
    29.         private ArrayList< Observer> allObservers = new ArrayList< Observer>();
    30.         // 添加一个观察者,即添加一个QQ好友
    31.         public void addObserver(Observer o) {
    32.                 this.allObservers.add(o);
    33.         }
    34.         // 添加一群观察者,即加入一个QQ群
    35.         public void addAll(ArrayList< Observer> observers) {
    36.                 this.allObservers.addAll(observers);
    37.         }
    38.         // 删除一个观察者,即删除一个QQ好友
    39.         public void deleteObserver(Observer o) {
    40.                 this.allObservers.remove(o);
    41.         }
    42.         // 删除一群好友,即退出一个QQ群
    43.         public void deleteAll() {
    44.                 this.allObservers = null;
    45.         }
    46.         // 当我上线时,通知所有QQ好友,即所有Observer
    47.         public void notifyObservers(String name) {
    48.                 for (Observer o : this.allObservers) {
    49.                         o.update(name);
    50.                 }
    51.         }
    52. }

    53. // 具体的被观察者,是某些Observer的观察主题
    54. class Subject01 extends AbstractSubject {
    55.         public void login(String name) {
    56.                 System.out.println("哈哈...蚂蚁-01 登录 QQ ...");
    57.                 // 立即通知所有QQ好友
    58.                 super.notifyObservers(name);
    59.         }
    60. }

    61. // 测试类
    62. public class Client {
    63.         public static void main(String[] args) {
    64.                 // 创建 蚂蚁-01 号
    65.                 Subject01 subject01 = new Subject01();
    66.                 // 为 蚂蚁-01 号添加好友
    67.                 Observer observer01 = new Observer01();
    68.                 Observer observer02 = new Observer02();
    69.                 Observer observer03 = new Observer03();
    70.                 subject01.addObserver(observer01);
    71.                 subject01.addObserver(observer02);
    72.                 subject01.addObserver(observer03);
    73.                 // 蚂蚁-01 号 登录,好友们马上会被通知
    74.                 subject01.login("蚂蚁-01 号");
    75.                
    76.                 System.out.println();
    77.                
    78.                 // 假如对QQ好友-03隐身,则以后他不会被通知
    79.                 subject01.deleteObserver(observer03);
    80.                 subject01.login("蚂蚁-01 号");
    81.         }
    82. }
    83. 测试结果:
    复制代码
    哈哈...蚂蚁-01 登录 QQ ...
    QQ好友-01 得知 蚂蚁-01 号上线了
    QQ好友-02 得知 蚂蚁-01 号上线了
    QQ好友-03 得知 蚂蚁-01 号上线了 哈哈...蚂蚁-01 登录 QQ ...
    QQ好友-01 得知 蚂蚁-01 号上线了
    QQ好友-02 得知 蚂蚁-01 号上线了

    很简单的模拟大概就这样了,上面的代码中只有一个具体Subject01类,而现实生活中具体Subject类与具体Observer类是多对多的关系的,比上面的实现要复杂得多。顾名思义,Observer模式,肯定 Observer类 是相当重要的,它在接收到 具体Subject 的状态改变之后,必须及时进行响应,处理相关事宜。上面的代码中则是得知自己的某个QQ好友上线了。 看一下 Observer 模式的优点: 1、具体 Subject 和具体 Observer 并没有紧耦合,可以各自扩展。在QQ例子中,在本质上 Subject 与 Observer 具有相同的身份,既是观察者也是被观察着,就相当于每个QQ用户都可以不理会自己已有的好友而在添加、删除某一QQ用户,这就是抽象耦合; 2、有时候我们的通知信息是一层一层地传递下去的,此时就形成了一条信息链,这也可以用 Observer 模式来实现,让某个具体 Observer 处理(即 update)信息、事件时出发另一个具体 Observer 对象也进行某些相应操作,也称为触发链,即一个处理序列。不过,多层次的触发回导致更高的复杂性,得把握得好这个度; Observe 模式与 Chain of Responsibility 模式的对比: 对于上面的触发链,我们可以对比一下职责链模式(Chain of Responsibility),两者都有信息的链传递,不同的是职责链中的信息通常是在传递中不变的,因为该信息旨在遍历整条链而找到第一个能够处理该信息的节点;而 Observer 模式中,假如有触发链,那么这里的信息可能是经过一层一层的“处理-触发-处理-…”逐步变化的。 说到这里,我个人感觉触发链的机制好像有点像复杂事件处理(CEP),可以比较着了解一下。链接地址:http://www.slideshare.net/Fenng/cep-3915346 Observer 模式的麻烦点: 1、对于某一个具体 Subject 的状态改变,所有具体 Observer 必须逐步 update() ,即业务逻辑处理,如果 Observer 集合过大,那么遍历性能是个问题; 2、根据上面的性能问题,时间延迟也是个问题,如果某个 Observer 需要尽快进行 update() ,如果被长时间堆叠在最后,那就糟了。此时可以用多线程异步进行处理,而多线程中的异步机制又必须保证线程安全。问题一个接一个… 最后,java 中实际上已经将 Observer 模式囊括在内了,大家看一下文档中 java.util.Observer 接口和 java.util.Observable 类即可,其中的 Observable 相当于 Subject 类。可以试着实现一下。 本文出自 “蚂蚁” 博客,请务必保留此出处http://haolloyin.blog.51cto.com/1177454/35
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 17:17 , Processed in 0.367045 second(s), 48 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表