Как сделать, чтобы другие классы были производными от одноэлементного класса? - PullRequest
5 голосов
/ 22 октября 2009

Извините, если это дубликат или слишком элементарный, но как мне сделать одноэлементный класс, который можно разделить на подклассы?

Ответы [ 6 ]

11 голосов
/ 22 октября 2009

У Стива Йегге есть забавная статья о синглетонах, в которой упоминается подкласс в этой цитате:

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

5 голосов
/ 22 октября 2009

Вы вообще не можете, в любом полезном смысле. Это было бы еще одной причиной не использовать синглтон-классы.

3 голосов
/ 22 октября 2009

На самом деле, я не думаю, что это возможно.

Вы создаете синглтон класса, объявляя его конструктор (ы) равным private. Но если вы затем попытаетесь объявить подкласс вашего синглтон-класса, конструктор подклассов не сможет увидеть конструкторы суперкласса ... поэтому они не будут компилироваться; например,

public class A () {
    private A() { }
}

public class B () {
    private B() { }
}

И компилятор Sun JDK 1.6, и Eclipse Ganymede выдают ошибку компиляции в конструкторе B, в результате чего конструктор no-args для A не виден.

Вы можете увеличить видимость конструкторов private, но тогда ничто (кроме здравого смысла) не мешает кому-то создавать несколько его экземпляров. Другими словами, это уже не единственный класс.

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

1 голос
/ 22 октября 2009

Синглтон ограничивает экземпляры, а не наследование. Что ж, - как уже было сказано, это ограничивает полезность наследования, и тогда вы можете перевести приватный конструктор в упакованный или защищенный (что, как вы можете утверждать, уменьшает одноэлементность синглтона). Но какова цель?

1 голос
/ 22 октября 2009

Если вы определили свой синглтон как:

public class Singleton {
  private static Singleton instance;
  public static Singleton getInstance() {
     if (instance == null) {
       instance = new Singleton();
     }
     return instance;
  }
  private Singleton() {
  }
}

Тогда вы можете просто сделать:

public class NewSingleton extends Singleton {
}

Но вы не сможете использовать приватные методы, поэтому, если вы хотите использовать синглтон, вам все равно нужно будет вызвать Singleton.getInstance();, чтобы вы ничего не получили, расширяя его.

Но нет никаких причин, почему вы не можете это сделать.

Теперь, если вы хотите добавить больше функций в класс Singleton, вы можете использовать межтиповые аспекты из AspectJ и просто внедрить новые методы / свойства в Singleton, которые затем могут использоваться Singleton.

0 голосов
/ 22 октября 2009

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

ответить на ваш вопрос; предполагая, что выбор для конкретного подкласса, который использует ваше приложение, определен, например, в системных свойствах, вы можете сделать что-то вроде:

public static synchronised Singleton getInstance() {
    if (instance == null) {
        String clsName = System.getProperties().getProperty("singleton.class");
        if (className == null || 0 == clasName.length()) {
            instance = new Singleton();
        } else {
            Class cls = Class.forName(clsName);
            instance = (Singleton) cls.newInstance();
        }
     }
     return instance;
}

Отказ от ответственности: непроверенный код, добавление обработки исключений и т. Д. :-) Кстати, убедитесь, что ваш getInstance() метод синхронизирован.

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