Как сделать, чтобы другие классы были производными от одноэлементного класса?

StackOverflow https://stackoverflow.com/questions/1605083

  •  05-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

  

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

Другие советы

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

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

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

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

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

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

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

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

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

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.

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

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

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

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 () синхронизирован.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top