IT박스

클래스간에 JAVA 콜백을 어떻게 수행합니까?

itboxs 2020. 11. 26. 08:05
반응형

클래스간에 JAVA 콜백을 어떻게 수행합니까?


이 질문에 이미 답변이 있습니다.

콜백이 매우 쉬운 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.");
};

부분, 부모 클래스에서 분명히 정확하지 않습니까?


인터페이스를 정의하고 콜백을받을 클래스에서 구현합니다.

귀하의 경우 멀티 스레딩에주의하십시오.

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);
        }
    }
}

멀티 스레딩

Remember this does not handle multi-threading, this is another topic and can have various solutions depending on the project.

The observer-pattern

The observer-pattern does nearly this, the major difference is the use of an ArrayList for adding more than one listener. Where this is not needed, you get better performance with one reference.


Use the observer pattern. It works like this:

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

You create an interface which has one or more methods to be called when some event happens. Then, any class which needs to be notified when events occur implements this interface.

This allows more flexibility, as the producer is only aware of the listener interface, not a particular implementation of the listener interface.

In my example:

MyClass is the producer here as its notifying a list of listeners.

MyListener is the interface.

MyForm is interested in when somethingHappened, so it is implementing MyListener and registering itself with MyClass. Now MyClass can inform MyForm about events without directly referencing MyForm. This is the strength of the observer pattern, it reduces dependency and increases reusability.


IMO, you should have a look at the Observer Pattern, and this is how most of the listeners work


I don't know if this is what you are looking for, but you can achieve this by passing a callback to the child class.

first define a generic callback:

public interface ITypedCallback<T> {
    void execute(T type);
}

create a new ITypedCallback instance on ServerConnections instantiation:

public Server(int _address) {
    serverConnectionHandler = new ServerConnections(new ITypedCallback<Socket>() {
        @Override
        public void execute(Socket socket) {
            // do something with your socket here
        }
    });
}

call the execute methode on the callback object.

public class ServerConnections implements Runnable {

    private ITypedCallback<Socket> callback;

    public ServerConnections(ITypedCallback<Socket> _callback) {
        callback = _callback;
    }

    @Override
    public void run() {   
        try {
            mainSocket = new ServerSocket(serverPort);
            while (true) {
                callback.execute(mainSocket.accept());
            }
        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

btw: I didn't check if it's 100% correct, directly coded it here.


In this particular case, the following should work:

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

It's an anonymous subclass.

참고URL : https://stackoverflow.com/questions/18279302/how-do-i-perform-a-java-callback-between-classes

반응형