Как сделать, чтобы другие классы были производными от одноэлементного класса?
Вопрос
Извините, если это дубликат или слишком элементарный, но как мне сделать одноэлементный класс, который можно разделить на подклассы?
Решение
У Стива Йегге есть забавная статья о синглетонах, в которых упоминается подклассы в этой цитате
Тогда есть вещь подкласса. Это почти невозможно подкласс Синглтон, и если вам это удастся, то Вы не должны были использовать Синглтон на первом месте. Вы не даже хочу туда пойти. Я гуляли дороги, которые я не смею пересказать. Просто притворись, что ты не можешь этого сделать, и вы сэкономите себе невероятные суммы боли.
Другие советы
Вы вообще не можете, в любом полезном смысле. Это было бы еще одной причиной не использовать синглтон-классы. Р>
На самом деле, я не думаю, что это возможно.
Вы создаете синглтон класса, объявляя его конструктор (-ы) 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 ()
синхронизирован.