微信和QQ这么多群,该如何管理好友关系?
本文节选自《设计模式就该这样学》
1 中介者模式的应用场景
在现实生活中,中介者的存在是不可缺少的,如果没有了中介者,我们就不能与远方的朋友进行交流。各个同事对象将会相互进行引用,如果每个对象都与多个对象进行交互,则会形成如下图所示的网状结构。
从上图可以看到,每个对象之间都过度耦合,这样既不利于信息的复用也不利于扩展。如果引入中介者模式,则对象之间的关系将变成星形结构,如下图所示。
从上图可以看到,使用中介者模式后,任何一个类的变化,只会影响中介者和类本身,不像之前的设计,任何一个类的变化都会引起其关联的所有类的变化。这样的设计大大减少了系统的耦合度。 其实日常生活中我们每天都在刷的朋友圈,就是一个中介者。还有我们所见的信息交易平台,也是中介者模式的体现。
中介者模式是用来降低多个对象和类之间的通信复杂性的。这种模式通过提供一个中介类,将系统各层次对象间的多对多关系变成一对多关系,中介者对象可以将复杂的网状结构变成以中介者为中心的星形结构,达到降低系统的复杂性、提高可扩展性的作用。 若系统各层次对象之间存在大量的关联关系,即层次对象呈复杂的网状结构,如果直接让它们紧耦合通信,会使系统结构变得异常复杂,且当其中某个层次对象发生改变时,则与其紧耦合的相应层次对象也需进行修改,系统很难进行维护。 简单地说,如果多个类相互耦合,形成了网状结构,则考虑使用中介者模式进行优化。总结一下,中介者模式主要适用于以下应用场景。
(1)系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
(2)交互的公共行为,如果需要改变行为,则可以增加新的中介者类。
2 中介者模式的UML类图
中介者模式的UML类图如下图所示。
3 使用中介者模式设计群聊场景
假设我们要构建一个聊天室系统,用户可以向聊天室发送消息,聊天室会向所有用户显示消息。实际上就是用户发信息与聊天室显示的通信过程,不过用户无法直接将信息发给聊天室,而需要将信息先发到服务器上,然后服务器再将该消息发给聊天室进行显示,具体代码如下。首先创建User类。
public class User { private String name; private ChatRoom chatRoom; public User(String name, ChatRoom chatRoom) { this.name = name; this.chatRoom = chatRoom; } public void sendMessage(String msg) { this.chatRoom.showMsg(this, msg); } public String getName() { return name; } }
然后创建ChatRoom类。
public class ChatRoom { public void showMsg(User user, String msg) { System.out.println("[" + user.getName() + "] :" + msg); } }
最后编写客户端测试代码。
public static void main(String[] args) { ChatRoom room = new ChatRoom(); User tom = new User("Tom",room); User jerry = new User("Jerry",room); tom.sendMessage("Hi! I am Tom."); jerry.sendMessage("Hello! My name is Jerry."); }
运行结果如下图所示。
4 中介者模式在JDK源码中的应用
首先来看JDK中的Timer类。打开Timer的结构,我们发现Timer类中有很多schedule()重载方法,如下图所示。
任意点开其中一个方法,我们发现所有方法最终都调用了私有的schedule()方法,源码如下。
public class Timer { ... public void schedule(TimerTask task, long delay) { if (delay < 0) throw new IllegalArgumentException("Negative delay."); sched(task, System.currentTimeMillis()+delay, 0); } ... private void sched(TimerTask task, long time, long period) { if (time < 0) throw new IllegalArgumentException("Illegal execution time."); if (Math.abs(period) > (Long.MAX_VALUE >> 1)) period >>= 1; synchronized(queue) { if (!thread.newTasksMayBeScheduled) throw new IllegalStateException("Timer already cancelled."); synchronized(task.lock) { if (task.state != TimerTask.VIRGIN) throw new IllegalStateException( "Task already scheduled or cancelled"); task.nextExecutionTime = time; task.period = period; task.state = TimerTask.SCHEDULED; } queue.add(task); if (queue.getMin() == task) queue.notify(); } } ... }
而且,不管是什么样的任务都被加入一个队列中按顺序执行。我们把这个队列中的所有对象都称为“同事”。同事之间的通信都是通过Timer来协调完成的,Timer承担了中介者的角色。 关注微信公众号『 Tom弹架构 』回复“设计模式”可获取完整源码。
本文为“Tom弹架构”原创,转载请注明出处。技术在于分享,我分享我快乐!
如果本文对您有帮助,欢迎关注和点赞;如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。关注微信公众号『 Tom弹架构 』可获取更多技术干货!
- 如何合理利用微信分组做好微信好友的管理
- 高仿微信6.3.31,使用网易云信SDK 3.2.0版本完成主要的聊天功能(单聊、群聊)、好友关系管理、群组管理等功能。
- iOS QQ、QQ空间、微信好友、微信朋友圈分享成功如何显示图文
- 分享本地视频到微信好友和QQ好友
- MUI分享链接到微信好友、朋友圈、QQ好友(终极版)
- 如何弹出QQ临时对话框实现不添加好友在线交谈效果
- 如何避免QQ/微信中的链接域名出现已停止访问该网页
- Maven项目中如何对具有继承关系的项目的jar进行统一管理
- 社会关系管理-如何管理个人关系创造价值?
- 在qq里面不加对方为好友 如何聊天
- QQ/微信里被禁止访问的网页怎么处理 被屏蔽的域名如何正常访问
- 如何让微信好友“爱”上你
- 微信官方:我们是如何打败QQ的?
- 如何弹出QQ临时对话框,实现不添加好友的在线交谈效果。
- QQ是如何实现好友桌面快捷方式的?
- 如何检测手机系统,如何检测页面是微信还是QQ打开
- 交互设计师和产品经理必读,推荐《QQ阅读 设计之路》讲述了QQ阅读的前世、今生、来世。面对这么多业界的阅读器,QQ阅读如何脱颖而出,占据市场,一起看看QQ阅读的发展过程。
- 仿微信/QQ 开发基于XMPP的iPhone/iOS聊天客户端(一)好友资料
- 如何弹出QQ临时对话框实现不添加好友在线交谈效果
- 如何使用USER.DB找回丢失QQ中的好友?