Ну, из вашего поста, даже если это не ясно сказано, звучит так, будто вы хотите, чтобы абстрактный класс играл две разные роли. Ролей являются:
- абстрактного завод роли для (Singleton) служб , который может иметь несколько взаимозаменяемых реализаций,
- интерфейс службы роли ,
плюс вы хотите сервис, который будет использоваться в одиночном режиме, «singletoness» во всем семействе классов, по какой-то причине вам недостаточно кэшировать экземпляр службы.
Это прекрасно.
Кто-то скажет, что он плохо пахнет, потому что «нарушает разделение проблем», а «синглтоны и модульные тесты не идут хорошо вместе».
Кто-то еще скажет, что это нормально, потому что вы даете ответственность за создание прав детей в самой семье, статический метод.
Неправильно то, что после того, как вы захотите, чтобы дети несли ответственность за выбор того, какую реализацию должен вернуть родительский заводский метод. Это неправильно с точки зрения дизайна, потому что вы делегируете всем детям то, что можно просто подтолкнуть и централизовать в абстрактный суперкласс, а также продемонстрировать, что вы смешиваете шаблоны, которые используются в разных контекстах, Abstract Factory (родительский решает, какое семейство клиенты классов будут получать) и Factory Method (детские заводы выбирают то, что получат клиенты).
Фабричный метод не просто не требуется, но также невозможен с помощью заводских методов, поскольку он сосредоточен на реализации или переопределении методов «экземпляра». Нет такой вещи, как переопределение для статических методов или конструктора.
Итак, возвращаясь к первоначальной хорошей или плохой идее абстрактного синглтона, который выбирает, какое поведение выставлять, есть несколько способов решить начальную проблему, Можно было бы выглядеть следующим образом, выглядит плохо, но я думаю, что это близко к чему Вы искали:
public abstract class A{
public static A getInstance(){
if (...)
return B.getInstance();
return C.getInstance();
}
public abstract void doSomething();
public abstract void doSomethingElse();
}
public class B extends A{
private static B instance=new B();
private B(){
}
public static B getInstance(){
return instance;
}
public void doSomething(){
...
}
...
}
//do similarly for class C
Родитель мог также использовать отражение.
Другим решением, дружественным к среде и расширением, является просто наличие детей, которые не являются одиночными, но упакованы в какой-либо внутренний пакет, который вы задокументируете как «частный» и абстрактный родитель, который может выставить статический getInstance() и «singleton mimiking» будет кэшировать дочерние экземпляры, обеспечивающие, чтобы клиенты всегда получали один и тот же экземпляр службы.
Цель частного конструктора в Синглтоне состоит в том, чтобы помешать кому-либо еще его создавать. Я достиг этого здесь - вы не можете создать экземпляр абстрактного класса, а подкласс имеет частный конструктор. – Simon
Это не приводит к тому, что подкласс является абстрактным и имеет только частный конструктор. – BalusC
Singleton не создает _require_ частный конструктор (см. Мой ответ для решения этого вопроса с помощью открытого конструктора). – ryvantage