2014-06-15 2 views
7

둘러 보았지만 찾고있는 것을 정확히 찾을 수 없습니다.Java : 배열에 메서드 호출을 저장하고 나중에 실행 하시겠습니까?

내가 무슨 일을하는지는 지정된 크기의 bufferedImage를 작성하여 JPanel에서 그릴 수있는 영역을 나타내는 클래스를 정의하고이 이미지 그래픽을 사용하여 이미지를 doubleBuffer로 그런 다음이 영역은 상위 JPanel에 이미지로 그려져 경계선을 만지는 모든 패널에 의존하는 javax의 미친 패널 구성 논리를 처리하지 않고 패널 영역을 만듭니다. 이것은 본질적으로 그래픽 위젯을위한 그래픽 컨텍스트로서 비디오 게임 UI와 유사하게 이동/크기 조정 등이 가능합니다.

내가 뭘하려는 건 그래픽 클래스, 매개 변수가 포함 된 작업을 그리는 메서드 호출을 저장할 수 있어야합니다. 이 목적은 런타임 또는 소스 코드에서 매개 변수의 값이 이미 지정된 메서드를로드 할 수 있도록하는 것입니다. 캡슐화를 중단하지 않고도 호출 할 수 있습니다. 부모 클래스가 직접 그리거나 버퍼링 된 이미지에 피할 수있는 방식을 사용하여 런타임에 메서드를 추가하거나 드로잉을위한 메서드 호출을 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(); 
} 
} 

, 내가 찾은 본질적으로 유일한 해결책은 당신이 할 수있다 추상 적으로 reflector 클래스를 사용하여 배열에 메서드를로드합니다. 그러나 실행하려면 해당 메서드의 매개 변수 값을 보내야합니다. 소스 코드에서 본질적으로 복잡한 메서드 호출을 만듭니다. 나는 그 단계를 자르거나 그 방법이 내가 주어진 값으로 스스로를 수행 할 수 있도록하고 싶다.

+1

참조 [커맨드 패턴 (http://en.wikipedia.org/wiki/Command_pattern) – Bohemian

답변

10

당신이하려는 것은 Command Pattern입니다.

Java에서이 작업을 수행하는 간단한 방법은 Runnable을 구현하는 익명 클래스를 만드는 것입니다. Runnable은 단일 메서드 인 void run()을 정의하는 인터페이스입니다. 코드에서 익명의 클래스를 구현할 수 있으며, 할 때 현재 범위의 모든 변수를 참조 할 수 있습니다.

Java 8의 경우 functional interfaces and lambda expression에 통사론을 추가하면 훨씬 쉽게 처리 할 수 ​​있습니다. 귀하의 질문의 코드는 자바 8과 같을 것이다 :

Graphics graphics = panelRegion.getGraphics(); 

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

panelRegion.addMethod(methodCall); 

아직 자바 (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(); 
     } 
    } 
} 
+0

실행 가능한 비트를 추가해 주셔서 감사합니다. 나는 이미 위키 피 디아 (위키 피 디아)에서 명령 구조를 찾아 보았지만 효과가 있었지만 몇 가지 문제가있었습니다. 이것은 훨씬 쉽고 안정적으로 작동했습니다. – user3743139

1

+1 @Phillipp 대답. 또한 메서드에서 반환 할 개체가있는 경우 Callable을 사용할 수 있습니다.자바 팔 아래를 들어

Graphics graphics = panelRegion.getGraphics(); 

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

panelRegion.addMethod(methodCall); 

:

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 
     } 
    } 
} 
관련 문제