Возможно ли иметь синглтон в заводском методе? У меня много доменов, использующих фабричный метод. Как мне обойти это. Пожалуйста, помогите мне с примером.
«... создайте интерфейс для объектов, которые создают экземпляры класса Singleton. По сути, это комбинация шаблонов Abstract Factory, Factory Method и Functor в книге GoF».
/**
* An interface defining objects that can create Singleton
* instances.
*/
public interface SingletonFactoryFunctor {
/**
* @return An instance of the Singleton.
*/
public Singleton makeInstance();
}
Вы должны вызвать ваш метод Singleton getInstance()
из фабричного метода. getInstance()
Логика должна обрабатывать детали возвращения одного экземпляра Singleton.
Синглтон вы можете реализовать как:
public class Singleton {
private static Singleton mInstance;
private Singleton(){}
public static Singleton getInstance()
{
if(mInstance==null){
mInstance=new Singleton();
}
return mInstance;
}
}
Этот класс вы можете возвращать в любом методе Factory, который хотите, как в mepcotterell, описанном ранее.
В этом примере, я полагаю, вы захотите синхронизировать свой метод getInstance (), чтобы два потока не вводили его одновременно. В противном случае два потока могут оказаться внутри блока, где создается экземпляр singleton, что очень проблематично. Единственная проблема с этим решением - вы платите премию за синхронизацию метода каждый раз, когда вызывается getInstance (). Пример:
public static synchronized Singleton getInstance()
{
// since whole method is synchronized only 1 thread can
// enter the following block ensuring only one instance
// is ever created. however we pay a synchronization
// penalty every time this method is called.
if(mInstance==null) {
mInstance=new Singleton();
}
return mInstance;
}
В качестве альтернативы вы также можете переключиться на активную инициализацию экземпляра синглтона вместо ленивой инициализации, если инициализация дешева, что гарантирует параллелизм, а также не платит синхронизированный штраф за вызов метода getInstance (). Пример:
// no synchronization penalty, but penalty for eager init
private static Singleton mInstance = new Singleton();
public static Singleton getInstance()
{
return mInstance;
}
Наиболее оптимизированный подход заключается в использовании двойной проверки блокировки, что необходимо для надежного использования Java 1.5 или новее из-за различных реализаций ключевого слова volatile в 1.4 или более старых JVM (см. Главу 5 «Шаблоны проектирования в первую очередь», стр. 182). опубликовано O'Reilly Media, Inc. - вот где я впервые прочитал об этом.) Пример:
private volatile static Singleton mInstance;
private Singleton(){}
public static Singleton getInstance()
{
if(mInstance==null) {
synchronized (Singleton.class) {
// only pay synchronization penalty once
if(mInstance==null){
mInstance=new Singleton();
}
}
}
return mInstance;
}
Этот пример не является формальным фабричным шаблоном (GoF), но все еще полезен, если вы используете его как статический фабричный метод
abstract class Product {}
class ConcreteProduct extends Product{}
class ProductSupportFactory {
private static ProductSupportFactory instance = null;
private ConcreteProduct product = null;
static {
instance = new ProductSupportFactory();
}
private ProductSupportFactory() {
product = new ConcreteProduct(); //object initialization
}
public static ProductSupportFactory getInstance(){
return instance;
}
public ConcreteProduct getProduct() {
return product;
}
public void setProduct(ConcreteProduct product) {
this.product = product;
}
}
public class ProductConsumer {
public static void main(String args[]){ //client
ConcreteProduct uniqueInstance = ProductSupportFactory.getInstance().getProduct();
ConcreteProduct sharedInstance = ProductSupportFactory.getInstance().getProduct(); //same object hash
}
}