Вам когда-нибудь нужно уничтожать экземпляр-одиночка? - PullRequest
13 голосов
/ 17 марта 2011

Используя синглтон, можно создать только один его экземпляр.Нужно ли нам когда-нибудь уничтожать этот экземпляр?

У меня есть одноэлементный DBManager, который управляет соединением JDBC и операциями запросов.Вызвав его статический метод newInstance, я могу получить его экземпляр, а затем выполнить несколько запросов.Наконец, я хочу закрыть соединение с базой данных и вызвать другой статический метод, закрывающий соединение JDBC.

Теперь соединение закрыто, а экземпляр DBManager все еще жив, но бесполезен.Нужно ли мне уничтожить его, например, присвоив ему значение null?В противном случае это может быть ошибочно указано позднее.

Если я назначу этот экземпляр с нулевым значением, то снова вызову метод newInstance, получу ли я другой новый другой экземпляр?

Ответы [ 8 ]

10 голосов
/ 17 марта 2011

Я бы не стал зацикливаться на семантике & ldquo; singleton & rdquo; & mdash; ваше требование заключается в том, чтобы в любой момент времени существовало не более одного экземпляра DBManager. Как только этот экземпляр становится бесполезным, вы можете либо уничтожить его, чтобы по запросу был создан свежий экземпляр, либо определить свой метод newInstance (который я мог бы предложить переименовать в getInstance), чтобы вызвать исключение (возможно, IllegalStateException ) если он вызывается после того, как синглтон стал бесполезным.

Если вы собираетесь уничтожить его, когда он станет бесполезным, я предлагаю сделать это внутри класса singleton автоматически, без посторонней помощи. Вам также следует подумать о том, чтобы полностью скрыть синглтон DBManager и внедрить шаблон делегирования. Это позволит избежать проблемы, связанной с тем, что клиент хранит ссылку на устаревший экземпляр DBManager. Затем вы можете сделать объект делегата обычным синглтоном.

5 голосов
/ 17 марта 2011

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

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

Так что подумайте, должно ли это быть одноэлементным - можете ли вы просто сделать его оболочкой для соединения, которое подключено соответствующим образом?

2 голосов
/ 17 марта 2011

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

Будет установлен параметр в пуле IDLE_CONNECTION_TIMEOUT или аналогичный, который автоматически истечет и закроет соединения, если они не используются в течение заданного периода времени.Так что в таких случаях разработчику не о чем беспокоиться.

2 голосов
/ 17 марта 2011

Я думаю, что было бы больше в соответствии с шаблоном Singleton, чтобы DBManager мог открывать и закрывать соединение, не разрушая сам DBManager.Затем вы сохраните его до следующего раза, когда вам понадобится соединение с базой данных, и попросите тот же объект DBManager создать новое соединение.В конце концов, если это DBManager, он управляет соединениями;оно не представляет отдельную связь.

0 голосов
/ 16 мая 2012

Создайте метод получения / установки для переменной класса и установите его равным нулю, чтобы создать экземпляр объекта Пример:

//Singleton support ...
private static A singleton = null;
    public static A get() {
        if (singleton == null){
        singleton = new A();
    }
        return singleton;
}
public static A getSingleton() {
    return singleton;
}
public static void setSingleton(A singleton) {
    A.singleton = singleton;
}

//Re instantiate 
public class Test(){
....
....
    A.setSingleton(null);

}
0 голосов
/ 17 марта 2011

Ответ должен быть нет вы не можете уничтожить синглтон, так как должен быть один и только один. Что касается вашей проблемы, у вас есть класс DBManager, соединение HASA которого закрыто и становится бесполезным.

Я предполагаю, что ваша цель должна состоять в том, чтобы одно соединение с БД было открыто одновременно, поэтому я хотел бы взглянуть на ваш код здесь: нарушаете ли вы принцип единственной ответственности и гарантируете, что вы разделяете ответственность за соединение на отдельный класс и предоставьте вашему единственному право управлять его соединениями - т.е. закрывать и открывать его по мере необходимости.

0 голосов
/ 17 марта 2011

Ваш класс DBManager должен обрабатывать очистку, если соединение БД закрыто. Т.е. если DBManager имеет ссылку на класс Connection, вы можете написать код в методе newInstance (), чтобы проверить, живо ли соединение, и вернуть статическую ссылку. как то так:

static DBManager manager;
static DBManager newInstance(){
if (manager == null) manager =new DBManager();
else if ( manager !=null && connection ==null) //if connection is closed 
manager =new DBManager();

return manager;
}
0 голосов
/ 17 марта 2011

Краткий ответ: Нет.

Более длинный ответ: Вы не можете уничтожить синглтон, если не используете специальный загрузчик классов.Если вам нужно уничтожить его, вы не должны использовать синглтон вообще.Может быть, вы можете переписать его таким образом, чтобы снова открыть - лучше: избегайте шаблона синглтона.

Поиск анти-паттерна или кода запаха.

...