信号和槽和java listener对比

信号和槽和java listener对比

简述


可能有朋友对其中一种不太熟悉。信号和槽、java listener 本质上都是一种发布/订阅模式。

具体实现


信号和槽看起来是这样:

class Sender: Object {
   // 定义信号
    public signal void some_event(int data);

    public void emit_event(int data) {
        some_event(data);
    }   
}

class Receiver: Object {
    // 槽函数
    public void handler(int data) {
        stdout.printf("received data: %d
", data);
    }   
}

void main() {
    var sender = new Sender();
    var receiver = new Receiver();

    sender.some_event.connect(receiver.handler);

    sender.emit_event(32);
}

上面这段代码用 vala 写成的。其它的如 qt 也只是写法不同,但是本质上还是一样的。运行结果:

received data: 32

java listener

public interface IListener {  
    void some_event(int data);  
}
public class Sender {  
    private IListener listener;  
  
    public void setListener(IListener listener) {  
        this.listener = listener;  
    }  
  
    public void emit_event(int data) {  
        if (listener != null)  
            listener.some_event(data);  
    }  
}
public class Receiver implements IListener {  
    @Override  
  public void some_event(int data) {  
        System.out.println("received data: " + data);  
    }  
}
public class App {  
    public static void main(String[] args) {  
        Sender sender = new Sender();  
        Receiver receiver = new Receiver();  
  
        sender.setListener(receiver);  
        sender.emit_event(32);  
    }  
}

执行结果:

received data: 32

二者实现的功能是一模一样的。但其中又有细微差别,看出差别在哪里了吗?

信号的定义和 listener 接口的定义相似,但是槽的优点在于:不需要显示申明实现 listener 接口,只要参数类型和顺序一致即可,也没有方法名的约束。换句话说,只要参数类型和顺序相同,都可以认为是该接口的实现,是不是有点像 go 的接口?

这个功能带来了很高的灵活性,比如某个信号要触发一个功能,这个功能在已有的库已经写好了,并且参数类型和顺序一致,我们只需要简单的连接一下即可,不再需要任何多余的粘合代码。