如何在前端创建一个信号槽?

101 阅读5分钟

可能有的人第一眼看到的不是前端创建这些文字,而是会问,什么叫做信号槽?

信号槽

信号槽(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();
        }
    }
}