Паттерн Java Singleton — это порождающий паттерн проектирования и одна из групп четырех паттернов проектирования. Шаблон проектирования Singleton — один из лучших способов создания объекта. Судя по определению, это относительно простой шаблон проектирования. Однако когда дело доходит до реализации, возникает несколько проблем с реализацией. Использование шаблона Java Singleton долгое время вызывало споры среди программистов.

За создание объекта в этом шаблоне отвечает один класс, при этом гарантируется, что будет создан ровно один объект.

Синглтон означает один экземпляр на контейнер. Например, если программа написана на Java, один экземпляр для JVM.

Нарушение общего принципа шаблона проектирования синглтона: при реализации синглтона не следует принимать никаких аргументов при создании экземпляра.

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

Мы рассмотрим шаблон Singleton на примере кода.

SingleObject.Java

public class SingleObject {
private static volatile SingleObject singleObject = new SingleObject();
private SingleObject() {
}
public static SingleObject getSingleObject() {
return singleObject;
}}

Singleton.java

public class Singleton {
public static void main(String[] args) {
SingleObject singleObject = SingleObject.getSingleObject();
System.out.println(singleObject);

SingleObject singleObject1 = SingleObject.getSingleObject();
System.out.println(singleObject);
}}

Фактический результат:

SingleObject@6504e3b2
SingleObject@6504e3b2

В приведенном выше фрагменте кода мы назначили две отдельные переменные, вызвали их в разное время и получили один и тот же экземпляр.

Не заходя дальше, что, если мы скорректируем код, как показано ниже?

public class SingleObject {
private static volatile SingleObject singleObject;
private SingleObject() {
if(singleObject !=null) {
throw new RuntimeException("Please use getSingleObject Method");
}}
public static SingleObject getSingleObject() {
if(singleObject==null) {
singleObject=new SingleObject();
}
return singleObject;
}}

Мы получили тот же результат после изменения SingleObject, потому что он был создан ранее; он вернул тот же экземпляр. Но тут есть проблема,

Предположим, что thread1 проходит через строку if(singleObject == null), проверяет ее значение null и присваивает значение этому singleObject переменная. Тем временем приходит thread2 и выводит строку if(singleObject == null)и спрашивает "is singleObject is null" поэтому thread1 еще не создан, он создается. С момента создания thread1 он сообщает «пустой». Таким образом, thread2 также входит. Это означает, что это не Thread Safe.

Чтобы предотвратить эту проблему, мы можем изменить класс SingleObject следующим образом.

public class SingleObject {
private static volatile SingleObject singleObject;
private SingleObject() {
if(singleObject !=null) {
throw new RuntimeException("Please use getSingleObject Method");
}}
public static SingleObject getSingleObject() {
if(singleObject==null) {
synchronized (SingleObject.class) {
if(singleObject == null) {
singleObject=new SingleObject();
}}}
return singleObject;
}}

Теперь здесь thread1 подходит к строке if(singleObject == null), так что это null и переходит к строке synchronized(SingleObject.class){}и получить блокировку. Затем снова перейдите внутрь к if(singleObject == null),да, это null. Теперь thread1 создает экземпляр. В то же время thread2 проверяет, является ли singleObject нулевым, да, он нулевой, потому что thread1 все еще создается. Затем перейдите к synchronized(SingleObject.class){}там написано "Вам не разрешен вход, потому что один парень уже внутри, и он работает над этим, так что ждите снаружи». Итак, теперь произошло то, что thread2 покидает блок, а затем синхронизирует блок, позволяя второму войти и продолжить создание экземпляра.

Спасибо за чтение! Если вам понравилось, ставьте аплодисменты и подписывайтесь на мою страницу.

Кишара Буддика