Как я могу иметь Singleton, который получен из абстрактного базового типа в Java? - PullRequest
11 голосов
/ 15 мая 2009

У меня есть несколько классов, которые используются как синглтоны. Они имеют некоторые базовые функциональные возможности и расширяют одного и того же предка из библиотеки, которая, в свою очередь, обычно не используется как синглтон.

Если я помещу общую функциональность в базовый класс, который наследует от общего предка, я получу класс, который не имеет смысла создавать экземпляры, поэтому я сделал его абстрактным. Кроме того, поскольку все классы используются как синглтоны, все они должны иметь метод 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;
    }
}

Я мог бы просто пропустить недопустимые строки в базовом классе и покончить с этим. Но как мне выразить, что каждый потомок Base должен иметь эти методы?

Ответы [ 4 ]

14 голосов
/ 15 мая 2009

Это невозможно в Java. Существование static методов не может быть применено; ни abstract, ни interface.

Моим решением было использовать IoC таким образом: я создал фабричный класс для синглетонов. Это сохранит синглтоны на карте. Ключом будет класс. Таким образом, я мог бы сказать:

A singleton = Factory.create (A.class);

Основное преимущество этого проекта: я могу создать метод Factory.replace(), в котором контрольные примеры могут переопределять синглетоны.

3 голосов
/ 15 мая 2009

Распространенный способ справиться с добавлением одноэлементной семантики в класс, для которого может быть неудобно правильно добавлять семантику, - это реализовать одноэлементную функциональность в классе-обертке. Например:

public class UsefulThing {

}

public final class SingletonOfUsefulThing {
    private static UsefulThing instance;

    private SingletonOfUsefulThing() {}

    public UsefulThing getInstance() {
        if (instance == null) {
            instance = new UsefulThing(); 
        }

        return instance;
    }
}

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

2 голосов
/ 15 мая 2009

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

На самом деле в этом не должно быть необходимости, поскольку статические методы будут вызываться только непосредственно для дочерних классов (A.init() и A.getInstance() в вашем примере) и никогда через ссылку на базовый класс (то есть статический методы не поддерживают полиморфизм).

1 голос
/ 15 мая 2009

Почему бы вам не пройти весь путь и не заставить свою фабрику (в базовом классе) передать параметр, указывающий, какой подкласс вы хотите вернуть. Есть много преимуществ для этого и несколько недостатков.

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

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