如何在类之间执行 JAVA 回调?

2022-08-31 13:06:06

我来自JavaScript,其中回调非常容易。我试图将它们实现到JAVA中,但没有成功。

我有一个父类:

import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {
    ExecutorService workers = Executors.newFixedThreadPool(10);
    private ServerConnections serverConnectionHandler;

    public Server(int _address) {
        System.out.println("Starting Server...");
        serverConnectionHandler = new ServerConnections(_address);

        serverConnectionHandler.newConnection = function(Socket _socket) {
            System.out.println("A function of my child class was called.");
        };

        workers.execute(serverConnectionHandler);

        System.out.println("Do something else...");
    }
}

然后我有一个子类,从父类调用:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ServerConnections implements Runnable {
    private int serverPort;
    private ServerSocket mainSocket;

    public ServerConnections(int _serverPort) {
        serverPort = _serverPort;
    }

    @Override
    public void run() {
        System.out.println("Starting Server Thread...");

        try {
            mainSocket = new ServerSocket(serverPort);

            while (true) {
                newConnection(mainSocket.accept());
            }
        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void newConnection(Socket _socket) {

    }
}

实施

serverConnectionHandler.newConnection = function(Socket _socket) {
    System.out.println("A function of my child class was called.");
};

部分,在父类中,这显然是不正确的?


答案 1

定义一个接口,并在将接收回调的类中实现它。

请注意您案例中的多线程。

http://cleancodedevelopment-qualityseal.blogspot.com.br/2012/10/understanding-callbacks-with-java.html 的代码示例

interface CallBack {                   

//declare an interface with the callback methods, 
//so you can use on more than one class and just 
//refer to the interface

    void methodToCallBack();
}

class CallBackImpl implements CallBack {          

//class that implements the method to callback defined 
//in the interface

    public void methodToCallBack() {
        System.out.println("I've been called back");
    }
}

class Caller {

    public void register(CallBack callback) {
        callback.methodToCallBack();
    }

    public static void main(String[] args) {
        Caller caller = new Caller();
        CallBack callBack = new CallBackImpl();       

//because of the interface, the type is Callback even 
//thought the new instance is the CallBackImpl class. 
//This alows to pass different types of classes that have 
//the implementation of CallBack interface

        caller.register(callBack);
    }
} 

在你的情况下,除了多线程之外,你可以这样做:

interface ServerInterface {
    void newSeverConnection(Socket socket);
}

public class Server implements ServerInterface {

    public Server(int _address) {
        System.out.println("Starting Server...");
        serverConnectionHandler = new ServerConnections(_address, this);
        workers.execute(serverConnectionHandler);
        System.out.println("Do something else...");
    }

    void newServerConnection(Socket socket) {
        System.out.println("A function of my child class was called.");
    }

}

public class ServerConnections implements Runnable {

    private ServerInterface serverInterface;
    
    public ServerConnections(int _serverPort, ServerInterface _serverInterface) {
      serverPort = _serverPort;
      serverInterface = _serverInterface;
    }

    @Override
    public void run() {
        System.out.println("Starting Server Thread...");

        if (serverInterface == null) {
            System.out.println("Server Thread error: callback null");
        }

        try {
            mainSocket = new ServerSocket(serverPort);

            while (true) {
                serverInterface.newServerConnection(mainSocket.accept());
            }
        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

多线程

请记住,这不能处理多线程,这是另一个主题,可以根据项目提供各种解决方案。

观察者模式

观察者模式几乎做到了这一点,主要区别在于使用 a 来添加多个侦听器。在不需要此功能的情况下,只需一个参考即可获得更好的性能。ArrayList


答案 2

使用观察点模式。它的工作原理如下:

interface MyListener{
    void somethingHappened();
}

public class MyForm implements MyListener{
    MyClass myClass;
    public MyForm(){
        this.myClass = new MyClass();
        myClass.addListener(this);
    }
    public void somethingHappened(){
       System.out.println("Called me!");
    }
}
public class MyClass{
    private List<MyListener> listeners = new ArrayList<MyListener>();

    public void addListener(MyListener listener) {
        listeners.add(listener);
    }
    void notifySomethingHappened(){
        for(MyListener listener : listeners){
            listener.somethingHappened();
        }
    }
}

您创建一个接口,该接口具有一个或多个要在发生某些事件时调用的方法。然后,任何需要在事件发生时通知的类都将实现此接口。

这允许更大的灵活性,因为生产者只知道侦听器接口,而不是侦听器接口的特定实现。

在我的例子中:

MyClass是这里的生产者,因为它的通知一个听众列表。

MyListener是接口。

MyForm对何时感兴趣,因此它正在实现并向 中注册自身。现在可以通知事件,而无需直接引用 。这是观察者模式的优势,它减少了依赖性并提高了可重用性。somethingHappenedMyListenerMyClassMyClassMyFormMyForm


推荐