2009-11-10 35 views
6

Điều tôi muốn làm là tải tập các lớp, có thể tất cả trong cùng một thư mục. Tất cả đều thực hiện cùng một giao diện và cùng một lớp, sau đó trong mã của tôi, tôi muốn có thể gọi các hàm trên các lớp đó.Java: Tải động nhiều phiên bản cùng loại

+0

này là không thể không chơi trò chơi với tùy chỉnh các trình nạp lớp (và thậm chí có thể không khả thi sau đó). Có thể nếu bạn giải thích những gì bạn đang cố gắng hoàn thành, bạn sẽ nhận được nhiều trợ giúp hơn. –

+0

OSGI trông rất thú vị tuy nhiên, có lẽ tôi đang tiếp cận vấn đề này không chính xác. Trong một ý nghĩa ít chung chung hơn đây là những gì tôi đang cố gắng để thực hiện. Tôi có một vỏ của trò chơi Oware chạy cơ chế trò chơi. Nó yêu cầu các lớp khác thực hiện các bước di chuyển của chúng bằng cách gửi cho chúng trạng thái của trò chơi và quay trở lại. Tôi muốn có một thư mục AI, mỗi mã chứa mã khác nhau, có thể có nhiều mã. Sau đó, hệ vỏ sẽ chạy một giải đấu vòng tròn trên tất cả các AI mà nó tìm thấy và đầu ra mà AI thắng được. – JonLeah

Trả lời

5

Dựa trên câu trả lời của bạn cho câu hỏi của tôi, có vẻ như bạn muốn xác định một giao diện trò chơi và sau đó cắm trong bất kỳ số lần triển khai AI nào, có thể được định cấu hình từ tệp .properties. Đây là cách sử dụng giao diện API khá chuẩn.

Bạn xác định một EngineInterface cung cấp phương thức chấp nhận trạng thái trò chơi và trả về di chuyển. Sau đó, bạn định nghĩa nhiều lớp mà tất cả đều thực hiện EngineInterface. Trình điều khiển của bạn đọc một tệp thuộc tính để lấy tên của các lớp thực hiện, khởi tạo chúng với Class.forName() và lưu trữ chúng trong một danh sách và/hoặc bản đồ. Sau đó, khi trình điều khiển nhận được yêu cầu, nó sẽ gọi mỗi lần thực hiện lần lượt và theo dõi kết quả.

1
  1. Nếu bạn có thể sử dụng OSGI, việc này đơn giản là chụp một ngón tay! Trong oSGI bạn có thể có nhiều câu trong cùng một lớp . Tất cả những gì bạn làm là có cùng một gói với các phiên bản khác nhau.

  2. Nếu không, bạn vẫn có thể viết trình tải lớp tùy chỉnh đọc cả hai lớp. Một cách để làm nó sẽ như thế này. Bạn viết hai ClassLoaders, một trong số chúng tải một phiên bản của lớp và lớp kia tải phiên bản khác của lớp đó. Bây giờ dựa trên nhu cầu bạn chọn classloader1 hoặc classloader2 để tải lớp. Vì vậy, bây giờ bạn cũng có thể có nhiều phiên bản của cùng một lớp được nạp đồng thời trong bộ nhớ.

Lưu ý: Hãy chắc chắn rằng đây là thực sự bạn muốn làm, có thể có cách khác để đến xung quanh vấn đề của bạn.

+0

tôi có thể có osgi? –

+0

@ jason ... tôi không hiểu bạn :) –

+5

"đơn giản như chụp một ngón tay" ... Đó là một tuyên bố táo bạo liên quan đến OSGi. – Thilo

1

Khung duy nhất tôi biết mà không hỗ trợ gì bạn đang sau là OSGI:

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

mô hình mạng của nó, được mô tả trong bài viết này "Exposing the boot classpath in OSGi", không cho phép điều đó

Một trong những hiệu ứng phụ (hoặc mục đích) của mô hình mạng là loại cách ly hoặc phiên bản lớp: nhiều phiên bản của cùng một lớp có thể cùng tồn tại độc đáo bên trong cùng một VM kể từ khi ea ch một được nạp vào mạng riêng của nó, không gian riêng của nó.

Xem tutorial này cho đầu và chọn trên eof khung OSGi (như Equinox, Knoplerfish hoặc Apache Felix)

2

Các bạn đã thử một cái gì đó như:

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; 

Mỗi lớp sẽ thực hiện thuật toán riêng của mình để tạo ra một động thái, nhưng sẽ được gọi nhưng gọi bằng phương pháp phổ biến

2

Có thể làm những gì bạn muốn với OSGI nhưng bạn cũng có thể sử dụng trình nạp lớp tùy chỉnh. Ý tưởng là bạn phải instanciate một bộ nạp lớp cho mỗi phiên bản của lớp bạn muốn tải.Here bạn có thể tìm thấy giải thích tốt.

Nhưng tôi nghĩ rằng những gì bạn thực sự cần phải giải quyết vấn đề của bạn là một cái gì đó dựa trên giao diện giống như mô tả bởi Jim Garrison hoặc Dave L Delaney ...

0

Nó có thể được thực hiện bằng việc nạp lớp năng động. Nó không tải lớp của phiên bản khác nhau nhưng các lớp con khác nhau của một lớp siêu hoặc giao diện.

Các bước quan trọng là:

(1) Sử dụng Class.forName (...) để tải lớp theo tên. Lớp phải nằm trong đường dẫn lớp.

(2) Sử dụng aClass.newInstance() để khởi tạo đối tượng. Điều này rất dễ dàng nếu không có tham số cần thiết cho hàm tạo.

Mã sau đây nên cung cấp một số ý tưởng cho bạn. Nó không xử lý ngoại lệ mà bạn phải làm điều đó.

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) { 
     // ... 
    } 
} 

Hy vọng điều này sẽ hữu ích.

0

Phản hồi của Jim rất tốt - bạn đặt tên cho các lớp bạn muốn sử dụng và tất cả đều phù hợp với một API chung. Tuy nhiên, giải pháp cho rằng tất cả các lớp đều có sẵn trên classpath của ứng dụng. Bạn có thể muốn có thể thêm nhiều triển khai sau này, ví dụ: sau khi ứng dụng được cài đặt.

Nếu đúng như vậy, có thể bạn sẽ cần sử dụng trình nạp lớp tùy chỉnh. Ví dụ, bạn có thể cho phép mọi người đặt các tệp jar bên trong một thư mục cụ thể ở đâu đó và thêm các tên lớp của các triển khai vào một tệp thuộc tính. Sau đó, bạn sẽ cần một trình nạp lớp tùy chỉnh hơn là có thể tải các lớp từ các jars bên trong thư mục đó và bạn sẽ sử dụng trình nạp lớp đó để tải các lớp (ví dụ: sử dụng Class.forName (className, classLoader)).

Thực tế nếu bạn có một trình nạp lớp cho mỗi tệp jar, bạn sẽ có thể có nhiều lớp có cùng tên trên các tệp jar, vì trình nạp lớp xác định ranh giới tên lớp. Điều này là khá nhiều những gì OSGI đang làm.

Dưới đây là một số mã liên quan đến các lớp học tải từ lọ:

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

Các vấn đề liên quan