2009-11-10 9 views
6

Co chciałbym móc zrobić, to załadować zestaw klas, prawdopodobnie wszystkie w tym samym folderze. Wszystkie implementują ten sam interfejs i są tej samej klasy, wtedy w moim kodzie chciałbym móc wywoływać funkcje na tych klasach.Java: Dynamicznie ładuj wiele wersji tej samej klasy.

+0

Nie jest to możliwe bez grania ze zwyczajem classloaders (a może nawet nie być możliwe). Może gdybyś wyjaśnił, co próbujesz osiągnąć, dostaniesz więcej pomocy. –

+0

OSGI wygląda jednak bardzo interesująco, być może niewłaściwie podchodzę do tego problemu. W mniej ogólnym znaczeniu, oto, co próbuję osiągnąć. Mam powłokę gry Oware, która uruchamia mechanikę gry. Prosi inne klasy, aby wykonały swoje ruchy, wysyłając im stan gry i zwracając ruch. Chciałbym mieć folder z AI, z których każda zawiera inny kod, może być ich wiele. Powłoka będzie wtedy prowadzić turniej rundy wszystkich badanych sztuczek, które wygrali przeciwko którymś z AI. – JonLeah

Odpowiedz

5

oparciu o odpowiedź na moje pytanie, wydaje chcesz zdefiniować interfejs gry, a następnie podłącz w dowolnej liczbie implementacji sztucznej inteligencji, prawdopodobnie skonfigurowanej z pliku .properties. Jest to dość standardowe użycie interfejsu API.

Definiujesz interfejs EngineInterface dostarczający metodę, która akceptuje stan gry i zwraca ruch. Następnie definiujesz wiele klas, które wszystkie implementują interfejs EngineInterface. Sterownik odczytuje plik właściwości, aby uzyskać nazwy klas implementacji, tworzy je za pomocą Class.forName() i zapisuje je na liście i/lub mapie. Następnie, gdy kierowca otrzymuje żądania, po kolei wywołuje każdą implementację i śledzi wyniki.

1
  1. Jeśli można użyć OSGi, jej tak proste, jak pęknięcia palca! W oSGI możesz mieć wiele wersji tej samej klasy . Wszystko, co musisz zrobić, to mieć te same pakiety w różnych wersjach.

  2. W przeciwnym razie można nadal pisać niestandardowy program ładujący klasy, który odczytuje obie klasy. Jednym ze sposobów robienia tego byłoby właśnie to. Piszemy dwie klasy ClassLoaders, jedna z nich ładuje jedną wersję klasy, a druga ładuje drugą wersję klasy. Teraz na podstawie potrzeby wybrania klasyloader1 lub classloader2 do załadowania klasy. Teraz możesz również załadować jednocześnie wiele wersji tej samej klasy w pamięci.

Uwaga: Upewnij to faktycznie chcesz zrobić, mogą istnieć inne sposoby zbliża się wokół problemu.

+0

mogę mieć osgi? –

+0

@jason ... nie dostałem ciebie :) –

+5

"tak proste jak zatrzaśnięcie palca" ... To jest odważne stwierdzenie odnośnie do OSGi. – Thilo

1

Jedynym ramy wiem który obsługuje co jesteś Po OSGI:

alt text http://blog.springsource.com/wp-content/uploads/2009/01/network.png

Jego model sieci, opisane w niniejszym artykule "Exposing the boot classpath in OSGi", zezwala że

Jednym z efektów ubocznych (lub celów) modelu sieciowego jest izolacja typu lub klasy: wiele wersji tej samej klasy może ładnie współegzystować wewnątrz tej samej maszyny wirtualnej, ponieważ ea ch jeden jest ładowany do własnej sieci, własnej przestrzeni.

Zobacz ten tutorial na początku i wybrać na EOF ram OSGI (jak Equinox, Knoplerfish lub Apache Felix)

2

Próbowałeś coś takiego:

class Move; // some data type that is able to represent the AI's move. 

interface AI { 

    Move getMove(GameState state); 
}; 

AIOne implements AI; 
AITwo implements AI; 

Każda klasa będzie realizować swój własny algorytm do generowania ruchu, ale byłoby nazwać ale wywołana przez wspólnej metody

2

Możliwe jest robić to, co chcesz z OSGI, ale równie dobrze możesz użyć niestandardowego programu ładującego klasy. Chodzi o to, że musisz zainicjować moduł ładujący klasy dla każdej wersji klasy, którą chcesz załadować.Here można znaleźć dobre wyjaśnienie. Ale myślę

czego naprawdę potrzebujesz, aby rozwiązać Twój problem jest coś oparte na interfejsach jak opisane przez Jim Garrison czy Dave L Delaney ...

0

Można to zrobić przy użyciu klasy dynamicznej załadunek. Nie ładuje klasy innej wersji, ale różni podklasy super klasy lub interfejsu.

ważne kroki to:

(1) Wykorzystanie Class.forName (...), aby załadować klasę według nazwy. Klasa musi znajdować się na ścieżce klasy.

(2) Użyj aClass.newInstance() do utworzenia instancji obiektu. Jest to łatwe, jeśli nie ma parametru wymaganego dla konstruktora.

Poniższy kod powinien dać ci pewien pomysł. Nie obsługuje wyjątków, które musisz zrobić.

class Context { 
    void moveUp(); 
    void moveDown(); 
    ... 
} 

interface AI { 
    void action(Context con); 
} 

public class Game { 
    public Game() { 
     Context aContext = new Context(); 
     String[] aAIClsNames = this.getAIClassNames("ai.list"); 
     AI[]  aAIs  = this.loadAI(aAIClsNames); 
     this.run(aAIs); 
    } 
    String[] getAIClassNames(String pAIClassListFile) { 
     // .. Load the file containning the AI-class file names 
    } 
    AI[] loadAI(String[] pAIClsNames) { 
     AI[] AIs = new AI[pAIClsNames.length]; 
     for(int i = 0; i < pAIClsNames.length; i++) { 
      String aAIClsName  = pAIClsNames[i]; 

      // (1) Get the class by name 
      Class<? extends AI> aAICls = Class.forName(aAIClsName); 

      // (2) Notice the cast as all of class in the list must implements AI 
      AIs[i] = (AI)aAICls.newInstance(); 
     } 
     return AIs; 
    } 
    void run(AI[] pAIs) { 
     // ... 
    } 
} 

Mam nadzieję, że to pomoże.

0

Odpowiedź Jima jest dobra - określasz klasy, z których chcesz korzystać, i wszystkie są zgodne z typowym interfejsem API. Jednak podane rozwiązanie zakłada, że ​​klasy są już dostępne w ścieżce klas aplikacji. Możliwe, że będziesz w stanie dodać więcej implementacji później, np. po zainstalowaniu aplikacji.

Jeśli tak jest, prawdopodobnie będziesz musiał użyć niestandardowego programu ładującego klasy. Na przykład można zezwolić użytkownikom na umieszczanie plików jar w określonym folderze i dodawanie nazw klas implementacji do pliku właściwości. Będziesz wtedy potrzebował niestandardowego programu ładującego klasy, który może załadować klasy z słoików znajdujących się w tym folderze, a ty użyjesz tego programu ładującego klasy do załadowania klas (np. Przy użyciu Class.forName (className, classLoader)).

W rzeczywistości, jeśli masz moduł ładujący klasy na plik jar, będziesz mógł mieć wiele klas o tych samych nazwach w plikach jar, ponieważ program ładujący klasy definiuje granice nazw klas. To właśnie robi OSGI.

Oto niektóre kodu odnoszące się do klas załadowczych od słoików:

http://sourceforge.net/projects/jcloader/ http://www.javaworld.com/javatips/jw-javatip70.html

Powiązane problemy