可能有的人第一眼看到的不是前端创建这些文字,而是会问,什么叫做信号槽?
信号槽
信号槽(Signal and Slot)是一种用于实现事件处理和通信的机制,最初由 Qt 框架引入。它主要用于在对象之间进行通信,以及在对象内部处理事件。
在信号槽机制中,一个对象可以向其他对象发送信号(Signal),而其他对象则可以通过连接槽(Slot)的方式来接收这些信号。当信号被发出时,所有连接到该信号的槽都会被触发,从而实现事件的处理和消息的传递。
信号槽机制具有以下优点:
- 低耦合性:信号槽机制可以将对象之间的通信解耦,使得它们彼此之间不需要知道对方的存在或实现细节,从而降低了耦合性。
- 灵活性:信号槽机制可以在运行时动态地建立和断开连接,从而使对象之间的关系更加灵活和可扩展。
- 扩展性:信号槽机制可以很容易地扩展和修改,而不需要对现有代码进行太多的更改。
观察者模式
信号槽和观察者模式(Observer Pattern)类似,观察者模式是一种行为型设计模式,也称作发布-订阅模式(Publish-Subscribe Pattern)。它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它会自动通知所有观察者对象,让它们能够及时作出相应的处理。
在观察者模式中,主题对象通常会维护一个观察者列表,当主题对象状态发生改变时,它会遍历观察者列表,依次调用每个观察者的更新方法,将新的状态信息传递给观察者,从而实现状态的同步更新。
观察者模式具有以下优点:
- 可以实现对象之间的松耦合关系,使得它们之间的交互更加灵活和可扩展。
- 可以让多个观察者对象同时监听一个主题对象,当主题对象发生变化时,可以避免出现紊乱和混乱的情况,从而提高代码的可维护性和可读性。
- 可以让观察者对象能够及时作出相应的处理,从而增强了系统的实时性和灵活性。
观察者模式也存在一些缺点,包括:
- 如果观察者对象过多或者更新处理过于复杂,可能会导致系统性能下降。
- 如果观察者对象与主题对象之间的依赖关系过于复杂,可能会导致代码难以理解和维护。
- 如果观察者对象之间的交互关系过于复杂,可能会导致代码的复杂度增加,从而降低了代码的可读性和可维护性。
大部分的设计模式技巧都会提升后期维护的人员的理解难度。除了一些简单的设计模式,这个将会在后续的文章中说明。
其实,如果我来设计后端通知功能的话,大致的实现思想也是类似。多个用户关注了某个用户,当这个用户发布新的内容或者动态的时候,查询所有的关系是follow的用户,并且将这个更新的信号推送给所有的关注用户,让他们知道自己关注的V更新了内容或者动态
select * from user where follow=13668 limit 20 offset 10
上面的SQL代码就是查询用户表中关注的是13668这个用户的第10页的20条数据。当我们查询到了关注的用户,然后就可以向这些用户进行推送他们关注的用户的动态了。至于是永消息队列推送动态还是直接推送,这个就是你们自己的选择了。
而前端中的代码也是类似的操作
class SinalSlot{
eventList:Array<Function>,
addHandler(callback:()=>void){
this.eventList.push(callback)
}
notify(){
this.eventList.foreach((event)=>{
event();
})
}
}
上面的代码中维护了一个名叫eventList的事件列表,每次进行监控的时候,就向eventList添加一个事件监听函数,当你需要通知监听对象进行某些操作的时候,就遍历这个列表中的所有监听函数。这也就是你监听的事件被触发了。这个和前端的emit概念如出一辙,也许编写Vue的小伙伴更为熟悉emit,emit也是观察者模式的实现,只不过我们熟知的是订阅/发布模式,因为在组件间传递消息常用这种模式。
其实如果设计的更完善的话,我们应该设计一个event类型在我们调用事件函数的时候传入这个函数当中。这样就能更加让这个观察者模式或者说信号槽模式更加完善了。能够让你更加方便的进行按需传入通知信号。或者说是订阅的消息。
附录:
Java实现这个信号槽
import java.util.ArrayList;
import java.util.List;
public class SignalSlot {
private List<Runnable> eventList = new ArrayList<>();
public void addHandler(Runnable callback) {
eventList.add(callback);
}
public void notify() {
for (Runnable event : eventList) {
event.run();
}
}
}