Как я могу реализовать абстрактный singleton-класс в Java?

Вот мой демонстрационный абстрактный singleton-класс:

public abstract class A {
    protected static A instance;
    public static A getInstance() {
        return instance;
    }
    //...rest of my abstract methods...
}

И вот конкретная реализация:

public class B extends A {
    private B() { }
    static {
        instance = new B();
    }
    //...implementations of my abstract methods...
}

К сожалению, я не могу заставить статический код в классе B выполняться, таким образом, переменная экземпляра никогда не устанавливается. Я попробовал это:

Class c = B.class;
A.getInstance() - returns null;

и это

ClassLoader.getSystemClassLoader().loadClass("B");
A.getInstance() - return null;

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

Я использую sun-java6-jre на Ubuntu 32bit для запущения этих тестов.

23
задан Simon 17 March 2010 в 00:01
поделиться

4 ответа

Абстрактный синглтон? Мне это не кажется жизнеспособным. Для шаблона Singleton требуется конструктор private , и это уже делает создание подклассов невозможным. Вам нужно будет переосмыслить свой дизайн. Шаблон Абстрактная фабрика может быть более подходящим для конкретной цели.

20
ответ дан 29 November 2019 в 02:04
поделиться

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

Я бы отделил создание объекта от самого фактического объекта и создал соответствующую фабрику , возвращающую определенный тип класса. Непонятно, как вы параметризуете это, учитывая ваш пример кода - параметризован ли он каким-либо аргументом, или выбор класса статичен?

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

4
ответ дан 29 November 2019 в 02:04
поделиться

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

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

4
ответ дан 29 November 2019 в 02:04
поделиться

В дополнение к проблемам, на которые указывали другие, наличие поля instance в A означает, что вы можете иметь только один singleton во всей VM. Если у вас также есть:

public class C extends A {
    private C() { }
    static {
        instance = new C();
    }
    //...implementations of my abstract methods...
}

... тогда любой из B или C, загруженный последним, выиграет, а экземпляр синглтона другого будет потерян.

Это просто плохой способ делать вещи.

3
ответ дан 29 November 2019 в 02:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: