簡體   English   中英

Java:在數組中存儲方法調用並稍后執行?

[英]Java: store method calls in an array and execute later?

我環顧四周但卻找不到我想要的東西。

我發生的事情是我有一個定義的類,用於表示JPanel中的一個區域,你可以通過創建一個指定大小的bufferedImage來繪制它,並將圖像圖形用於doubleBuffer到JPanel,然后將區域作為圖像繪制到父JPanel,基本上創建面板區域而不必處理javax的瘋狂面板組織邏輯,該邏輯取決於觸摸邊界的所有面板。 這實際上是圖形小部件的圖形上下文,可以移動/調整大小等,類似於視頻游戲UI。

我想要做的是我希望能夠存儲方法調用來繪制圖形類中的操作,包括參數。 這樣做的目的是,無論是在運行時還是在源代碼中,我都可以使用已經指定的參數值來加載方法,只需調用它而不必破壞封裝,因為它代表父類必須直接繪制對於bufferedimage,我想避免一些事情,以便可以在運行時添加方法,或者必須在PanelRegion類本身中完成繪制方法調用,迫使我每次想要另一個PanelRegion時創建一個新的專用PanelRegion,這將無法有效地工作。

我希望能做的只是:

Class graphics = panelRegion.getGraphics();
String methodName = "drawRectangle";
int xPos = 0;
int yPos = 0;
int width = 0;
int height = 0;

ImaginaryMethodClass method = graphics.getMethod(methodName, int, int, int, int);
method.imaginaryMethodThatLoadsParameterValues(xPos, yPos, width, height);

panelRegion.addMethod(method);
panelRegion.invokeDrawMethods();

public void invokeDrawMethods()
{
for(ImaginaryMethodClass aMethod : listOfMethods)
{
aMethod.imaginaryMethodThatExecutesTheMethodWithTheLoadedParameterValues();
}
}

如果這沒有意義,基本上我發現的唯一解決方案是你可以抽象地將方法加載到帶有反射器類的數組中,但是當你想要執行時你必須仍然發送該方法的參數的值,本質上使它成為一個復雜的方法調用源代碼。 我想要切出那個步驟或者做出來讓方法可以用我給出的值來執行。

你要做的是稱為命令模式

在Java中執行此操作的一種簡單方法是創建一個實現Runnable的匿名類。 Runnable是一個定義單個方法的接口: void run() 您可以在代碼中的任何位置實現匿名類,並且在執行時,可以引用當前范圍中的任何變量。

通過為函數接口和lambda表達式添加一些語法糖,Java 8使這變得更容易。 您的問題中的代碼在Java 8中將如下所示:

Graphics graphics = panelRegion.getGraphics();

Runnable methodCall = () ->  graphics.drawRectangle(xPos, yPos, width, height);

panelRegion.addMethod(methodCall);

當你還沒有使用Java 8時,代碼有點復雜:

Graphics graphics = panelRegion.getGraphics();

Runnable methodCall = new Runnable() {
   public void run() {
       graphics.drawRectangle(xPos, yPos, width, height);
    }
}

panelRegion.addMethod(methodCall);

在上面的兩個(完全等效的)示例中,不執行graphics.drawRectangle(xPos, yPos, width, height) 它僅在methodCall.run()時執行。

panelRegion的實現將使用它將要執行的命令維護List<Runnable> 當它執行該列表時,它只調用每個列表上的.run()方法。

class PanelRegion {

    private List<Runnable> listOfMethods = new ArrayList<>();

    public void addMethod(Runnable methodCall) {
        listOfMethods.add(methodCall);
    }

    public void invokeDrawMethods()
    {
         for(Runnable aMethod : listOfMethods) {
             aMethod.run();
         }
    }
}

+1為@Phillipp回答。 此外,如果您有從方法返回的對象,則可以使用Callable

Graphics graphics = panelRegion.getGraphics();

Callable methodCall = () ->  graphics.drawRectangle(xPos, yPos, width, height);

panelRegion.addMethod(methodCall);

對於Java 8以下:

Graphics graphics = panelRegion.getGraphics();

Callable methodCall = new Callable() {
   @Override
   public Object call() {
       return graphics.drawRectangle(xPos, yPos, width, height);
    }
}

panelRegion.addMethod(methodCall);

並調用如:

class PanelRegion {
    private List<Callable> listOfMethods = new ArrayList<>();

    public void addMethod(Callable methodCall) {
        listOfMethods.add(methodCall);
    }

    public void invokeDrawMethods()
    {
         for(Callable aMethod : listOfMethods) {
             Object ret = aMethod.call();
             // do something with ret
         }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM