Java: разрешить создание экземпляров только одним классом - PullRequest
5 голосов
/ 20 августа 2011

Я хочу, чтобы определенные классы в моем проекте были объединены.И поэтому я не хочу иметь возможность создавать экземпляры этих классов, используя: new SomeClass (), а вместо этого получать новый элемент из пула, используя SomeClass.allocate ().У меня есть такой код для каждого класса, который требует объединения.

public class GameObject
{
    // Pooling: Provides a static method for allocation and a method for freeing
    private static Pool<GameObject> pool = new Pool<GameObject>();
    public static GameObject allocate() { return pool.obtain(); }
    public void free() { pool.free(this); }
    ...
}

Теперь я могу отключить обычный способ создания экземпляров, сделав конструктор по умолчанию закрытым, но проблема заключается в том, что пул должен создавать экземпляр классакогда он создается, а также когда необходимо расширить пул.

Есть ли способ ограничить построение только пулом?

Ответы [ 3 ]

2 голосов
/ 20 августа 2011

В крайнем случае, вы можете использовать отражение.Для другого варианта, другие люди уже рассказывают.Я помню, что Spring контейнер может инициализировать класс, который имеет приватный конструктор.И я удивлен этим.Я думаю, что это также использует этот трюк.Выгода может быть более общей.

public static void main(String... args) {
    try {
      Constructor c = GameObject.class.getDeclaredConstructor();
      c.setAccessible(true); // solution
      c.newInstance();

      // production code should handle these exceptions more gracefully
    } catch (InvocationTargetException x) {
      x.printStackTrace();
    } catch (NoSuchMethodException x) {
      x.printStackTrace();
    } catch (InstantiationException x) {
      x.printStackTrace();
    } catch (IllegalAccessException x) {
      x.printStackTrace();
    }
  }
2 голосов
/ 20 августа 2011

У меня есть два варианта: либо сделать его внутренним классом пула, либо сделать метод allocate приватным и поместить его в тот же пакет, что и пул.

РЕДАКТИРОВАТЬ: Ах. Просто сделайте конструктор закрытым, а затем переопределите любой метод, который Pool использует для создания новых экземпляров. В качестве (грубого) примера, используя ваш кадр выше:

public abstract class Pool<T>
{
    public abstract T getNewObject();

    public T obtain(){ return getNewObject(); }

    public void free(T obj) {}
}

и

public class GameObject
{
    // Pooling: Provides a static method for allocation and a method for freeing
    private static Pool<GameObject> pool = new Pool<GameObject>(){
          public GameObject getNewObject(){ return new GameObject(); }
    };
    public static GameObject allocate() { return pool.obtain(); }
    private GameObject(){}
    public void free() { pool.free(this); }
}
Конструктор

GameObject, к счастью, недоступен никому другому.

1 голос
/ 20 августа 2011

Альтернатива: не пытайтесь заставить свой код перескочить через обручи. Используйте статический анализ для обеспечения соблюдения таких правил. Инструменты поймают это, если вы случайно сделаете что-то, что не собирались делать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...