Как я могу получить синглтон, полученный из абстрактного базового типа в Java?
У меня есть некоторые классы, которые используются как синглтоны. Они имеют некоторые базовые функции и расширяют один и тот же предк из библиотеки, которая, в свою очередь, обычно не используется как Singleton.
Если я поместил общую функциональность в базовый класс, который наследуется от общего предка, я получаю класс, который не имеет смысла создавать экземпляр, поэтому я сделал его абстрактным. Кроме того, поскольку все классы используются как синглтоны, все они должны иметь метод init() и getInstance(), которые являются статическими. Все конструкторы, конечно, не являются общедоступными.
Теперь, поскольку static
является незаконным модификатором для абстрактных методов, следующее не работает, хотя это было бы именно то, что я хочу:
class Base extends LibraryClass {
protected Base() {
// ... constructor
}
// ... common methods
// ILLEGAL!
public static abstract void init();
public static abstract <T extends Base>T getInstance();
}
class A extends Base {
private static A _INSTANCE;
private A() {
super();
}
public static void init() {
_INSTANCE = new A();
}
public static A getInstance() {
return _INSTANCE;
}
}
Я мог бы просто оставить незаконные строки в базовом классе и сделать с ним. Но как я могу выразить, что каждый ребенок базы должен иметь эти методы?
Ответы
Ответ 1
Это невозможно в Java. Существование методов static
не может быть выполнено; ни с помощью abstract
, ни с помощью interface
.
Мое решение заключалось в том, чтобы использовать IoC в некотором смысле: я создал класс factory для одиночных чисел. Это спасло бы синглтоны на карте. Ключ будет классом. Таким образом, я мог бы сказать:
A singleton = Factory.create (A.class);
Основное преимущество этой конструкции: я могу создать метод Factory.replace()
, где тестовые примеры могут переопределять синглтоны.
Ответ 2
Общим способом справиться с добавлением синтаксической семантики к классу, для которого может быть неудобно правильно добавить семантику, является реализация одноэлементной функциональности в классе-оболочке. Например:
public class UsefulThing {
}
public final class SingletonOfUsefulThing {
private static UsefulThing instance;
private SingletonOfUsefulThing() {}
public UsefulThing getInstance() {
if (instance == null) {
instance = new UsefulThing();
}
return instance;
}
}
Это позволяет вам отдать некоторые из основных преимуществ одноэлементного класса для класса без каких-либо последствий, которые реализуют синтаксическую семантику в классе, что напрямую заставляет вас иметь дело, и позволяет некоторым помещениям для изменения определенного типа класса, re exposing как singleton (с помощью factory для создания экземпляра, например, вместо new
.
Ответ 3
Вы не можете выразить, что дочерние классы имеют определенные статические методы.
На самом деле не должно быть необходимости делать это, поскольку статические методы будут вызваны непосредственно на дочерние классы (A.init()
и A.getInstance()
в вашем примере) и никогда не будут ссылаться на базовый класс (т.е. статические методы не поддерживают полиморфизм).
Ответ 4
Почему бы вам не пройти весь путь и сделать ваш factory (в базовом классе) передать параметр, указывающий, какой подкласс вам нужно вернуть. Есть много преимуществ для этого, и несколько недостатков.
То, как вы пытаетесь это сделать, не имеет большого смысла, поскольку статические методы не имеют отношения к наследованию совершенно так же, как обычные методы.