2011-11-02 36 views
7

Vì vậy, tôi có một vài lớp 'Quản lý', ví dụ như GroupManager. Tất cả những người quản lý này đều là những người độc thân.Generics Java, singletons và phương thức tĩnh

Sử dụng phương pháp này cho instancing:

private static GroupManager groupManager = null; 

private GroupManager() 
{ 

} 

public static GroupManager Instance() 
{ 
    if (groupManager == null) 
    { 
     groupManager = new GroupManager(); 
    } 
    return groupManager; 
} 

Tôi nghĩ tôi nên bắt đầu sử dụng một số thừa kế khi họ có rất nhiều phương pháp sao chép.

Phương thức Instance() cho mỗi Trình quản lý giống nhau.

Vì vậy, cho thừa kế tôi có thể làm được điều này (rõ ràng):

GroupManager extends Manager 

Có thể sử dụng Generics để sử dụng phương pháp thẩm tương tự cho tất cả các nhà quản lý, một cái gì đó như:

public class Manager<E> 
{ 
    private static E instance = null; 

    public static E Instance() 
    { 
     if (instance == null) 
     { 
      instance = new E(); 
     } 
     return instance; 
    } 

} 

Tôi nghĩ điều đó có ý nghĩa :)

Vì vậy, bạn sẽ làm GroupManager.Instance() như bình thường.

+1

Java Generics là không có cách nào sự giống như C++ Templates! Để nó đi! Bạn không bao giờ có thể phân bổ một đối tượng (tức là gọi mới) bằng cách sử dụng một Java Generic. Thử tìm kiếm trên google cho "Java Type Erasure" – DwB

+0

Related: http://stackoverflow.com/questions/1927789/why-should-i-care-that-java-doesnt-have-reified-generics – BalusC

+0

Quản lý E là một tham chiếu đến loại chung. Không có cách nào đơn giản để thiết lập một lớp để phân bổ các đối tượng của một kiểu chỉ được biết đến trong thời gian chạy. Câu trả lời của Reid Mac là những gì tôi sẽ thử. – DwB

Trả lời

9

Bạn không hiểu cách hoạt động của generics và statics. Nếu bạn có một trường tĩnh hoặc phương thức (chẳng hạn như "instance" hoặc instance()), có thể được gọi mà không instantiating Manager Manager, làm thế nào bạn mong đợi JVM (và trình biên dịch thậm chí) để biết loại E được cho là gì được?

Dưới đây là một ví dụ, theo đề nghị của G_H của:

GeneralManager và AreaManager cả mở rộng quản lý

Lớp Manager là người duy nhất mà có getInstance() phương pháp tĩnh:

public class Manager { 

     private static Map<Class<? extends Manager>,Manager> INSTANCES_MAP = new java.util.HashMap<Class<? extends Manager>, Manager>(); 

//Also, you will want to make this method synchronized if your application is multithreaded, 
//otherwise you mihgt have a race condition in which multiple threads will trick it into 
//creating multiple instances 
     public static <E extends Manager> E getInstance(Class<E> instanceClass) throws InstantiationException, IllegalAccessException { 
      if(INSTANCES_MAP.containsKey(instanceClass)) { 
       return (E) INSTANCES_MAP.get(instanceClass); 
      } else { 
       E instance = instanceClass.newInstance(); 
       INSTANCES_MAP.put(instanceClass, instance); 
       return instance; 
      } 
     } 
    } 
+1

Vâng, nhưng điều đó hoàn toàn không hiệu quả với ý tưởng triển khai thực đơn. Bạn sẽ cần một số cấu trúc khủng khiếp méo mó như một Bản đồ từ 'Lớp' đến các thể hiện. –

+0

+1, điều đó rất đúng, tôi đã nghĩ liệu tôi có nên thêm quan sát đó hay không (tôi quyết định không làm cho tôi tin trước tiên những khái niệm cơ bản về generics và statics cần được hiểu trước khi được sử dụng như thế này). Tuy nhiên bạn thực hiện một điểm tốt. Hơn nữa, bạn có thể hạn chế kiểu E chung cho một lớp cơ sở như E mở rộng RootOfIheritanceChainClass. –

+0

Tôi bị mất lol, tôi nên đi với: về cơ bản tôi cần một phương thức Instance() mới cho mỗi Manager mới. – Metalstorm

2

Không, nó sẽ không hoạt động. Java sử dụng generics tại thời gian biên dịch để kiểm tra kiểu, nhưng không tạo ra các lớp phụ hoặc giữ lại thông tin liên quan đến các tham số kiểu khi chạy.

Khi bạn khai báo Manager<E> với thông số loại E, đó là thứ sẽ chỉ đóng vai trò trong một phiên bản thực tế. Bạn có thể có một lớp con như GroupManager extends Manager<String> hoặc bất cứ điều gì, nhưng đó không phải là kỳ diệu sẽ tạo ra một loạt các phương pháp tĩnh.

Phương pháp và thành viên tĩnh thuộc về một lớp, không phải là một cá thể. Vì vậy, cố gắng sử dụng generics ở đó, được thiết kế để đánh máy các trường hợp, sẽ không bay.

0

Nếu bạn đặt lớp người quản lý nhóm như sau, bạn có thể gọi phương thức thể hiện của mình.

public class GroupManager extends Manager<GroupManager>{} 

Và trong lớp Manager cố gắng này ...

public class Manager<E> 
{ 
private static E instance = null; 

public static E Instance() 
{ 
        try { 
      return instance.newInstance(); 
     } catch (InstantiationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     return null; 
} 

Hoặc nếu bạn biết đối tượng bạn muốn một ví dụ cho, chỉ cần thực hiện phương pháp chung

public static <T> T getInstance(Class<T> t){ 
      try { 
      return t.newInstance(); 
     } catch (InstantiationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     return null; 
    } 

tôi HAVN 't đã thử bất kỳ điều này vì vậy không chắc chắn nếu nó sẽ làm việc.

+1

ví dụ đầu tiên là sai – Fabian

0

Tiêm trình tạo trong ngữ cảnh chung.Tiền không phải là chủ đề an toàn, nhưng chỉ được sử dụng trong bối cảnh tĩnh rất tốt của nó nếu bạn không bỏ lỡ sử dụng nó

public class Example { 

    public static class MySingletonClass { 
    } 

    public interface Provider<T> { 
     T get(); 
    } 

    static final Provider<MySingletonClass> myClassInstanceProvider = new Cash<MySingletonClass>(new Provider<MySingletonClass>() { 
      @Override 
      public MySingletonClass get() { 
       return new MySingletonClass(); 
      } 
     }); 


    public static class Cash<T> implements Provider<T> { 
     private Provider<T> provider; 

     public Cash(Provider<T> provider) { 
      this.provider = provider; 
     } 

     @Override 
     public T get() { 

      final T t = provider.get(); 
      provider = new Provider<T>() { 

       @Override 
       public T get() { 
        return t; 
       } 
      }; 
      return t; 
     } 
    } 
} 
0

public class Manager<E>{ 

private static Object instance = null; 

    public static E Instance() { 
     if (instance == null) 
     { 
     instance = new E(); 
     } 
     return (E)instance; 
    } 
} 

+0

Câu trả lời ở trên sẽ làm, phải không? –

+0

thats sẽ không làm việc – Fabian

+0

mà doesnt 'làm việc ... – mahieddine

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