Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Singleton . (https://javascript.ru/forum/misc/5343-singleton.html)

Kolyaj 06.10.2009 14:39

Singleton .
 
Отвечу тут Дмитрию, на хабре дискутировать неудобно.

Singleton'у может понадобиться конструктор, который желательно вызвать в момент первого использования объекта. Тогда простой объект будет использовать неудобно.

Я вот здесь в конце статьи привел вариант реализации Singleton, но, честно говоря, сам им пока не пользовался :)

Dmitry A. Soshnikov 06.10.2009 15:18

Цитата:

Сообщение от Kolyaj
Отвечу тут Дмитрию

Цитата:

Сообщение от Kolyaj
Я вот здесь в конце статьи привел вариант реализации Singleton

Да, спасибо, я уже читал эту статью.

Цитата:

Сообщение от alljs.ru
Особенность этого метода заключается еще и в том, что если экземпляр класса не понадобится, то не создается не только экземпляр, но и сам класс. При этом ключевое слово new становится вовсе опциональным, главное скобочки не забыть.

На самом деле, если экземпляр не понадобится, то мы и не создадим этот объект. В твоём варианте, если экземпляр понадобится, будет создан и объект, и конструктор.

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

Но, в качестве теоретической имитации шаблона "Singleton" из классовой парадигмы, можно и использовать предложенный вариант, но, с практической точки зрения, я не вижу особой надобности.

Kolyaj 06.10.2009 15:45

Цитата:

Сообщение от Dmitry A. Soshnikov
На самом деле, если экземпляр не понадобится, то мы и не создадим этот объект.

В обычном варианте var S = {} он создастся в любом случае.

Dmitry A. Soshnikov 06.10.2009 16:02

Цитата:

Сообщение от Kolyaj
В обычном варианте var S = {} он создастся в любом случае.

Да, и это означает, что он нужен. Если не нужен - не создаётся (т.е. его нет в коде).

Dmitry A. Soshnikov 06.10.2009 17:28

Kolyaj, там же, на Хабре, приводят преимуществом наследование, с этим - согласен.

Kolyaj 06.10.2009 18:05

Цитата:

Сообщение от Dmitry A. Soshnikov
Если не нужен - не создаётся (т.е. его нет в коде).

var S = {...};
if (...) {
    // Здесь S нужен
} else {
    // А здесь не нужен
}


Цитата:

Сообщение от Dmitry A. Soshnikov
приводят преимуществом наследование

В моем варианте с наследованием туго :)

Dmitry A. Soshnikov 06.10.2009 18:25

Цитата:

Сообщение от Kolyaj
// Здесь S нужен

Цитата:

Сообщение от Kolyaj
// А здесь не нужен

Ну, всё правильно (даже, если динамически, по условию):

if (...) {
  var S = {};
} else {
  ...
}


В любом случае (и в твоей реализации тоже), переменная "S" уже будет в объекте переменных.

Ещё преимуществом можно выделить частые подобные проверки с if-ми-else-ами. Чтобы каждый раз не проверять, инициализирован ли уже объект (if typeof S !== 'undefined'), можно вынести его в геттер (который и называется в данном случае "Singleton"):

function getOurObject() {
  if (!arguments.callee.instance) {
    arguments.callee.instance = {...};
  }
  return arguments.callee.instance;
}


В общем, два преимущества:

1. Наследование (если нужно);
2. Улучшение code-reuse, чтобы сократить код (этот пункт, в данном случае, является разновидностью memoization).

Kolyaj 06.10.2009 18:37

Цитата:

Сообщение от Dmitry A. Soshnikov
if (...) {
  var S = {};
} else {
  ...
}

А если несколько таких if'ов?

Цитата:

Сообщение от Dmitry A. Soshnikov
В любом случае (и в твоей реализации тоже), переменная "S" уже будет в объекте переменных.

Переменная будет, но значения-то у нее не будет.

Dmitry A. Soshnikov 06.10.2009 18:40

Цитата:

Сообщение от Kolyaj
А если несколько таких if'ов?

Да, я это отметил:
Цитата:

Сообщение от Dmitry A. Soshnikov
Ещё преимуществом можно выделить частые подобные проверки с if-ми-else-ами. Чтобы каждый раз не проверять, инициализирован ли уже объект (if typeof S !== 'undefined'), можно вынести его в геттер

Цитата:

Сообщение от Kolyaj
Переменная будет, но значения-то у нее не будет.

Ну так и в простом случае (var S = {}) так же, разницы нет здесь.

Kolyaj 06.10.2009 18:42

Цитата:

Сообщение от Dmitry A. Soshnikov
Да, я это отметил:

И пришел в результате к синглтону, про который сказал в начале
Цитата:

На кой ляд? Если можно просто создать объект?
:)

Dmitry A. Soshnikov 06.10.2009 19:05

Цитата:

Сообщение от Kolyaj
И пришел в результате к синглтону

Ну, несомненно, в плане многих проверок - да. Но терминологию "Синглтон" и этот паттерн (при той же организации) можно и не использовать. Например, в плане Java-Swing-a или JavaScript-ового Ext-фреймворка (который вдохновлён Swing-ом) можно повсеместно видеть код:

getPanel: function () {
  if (!this.panel) {
    // вычисления и создание панели
  }
  return this.panel;
}

// и потом в 10 методах
// this.getPanel()


Я говорил об _этом_, когда упомянул разновидность memoization. Здесь ближе по _идеологии_ именно к этой сущности, но не к Singleton. Хотя, в определении "возвращает один и тот же объект" - да, можно и терминологию "Singleton" приплести. Если же это ещё подкрепить и оператором new, то вообще ещё больше похоже (но сути не меняет).

Цитата:

На кой ляд? Если можно просто создать объект?
А это в плане, когда нужен просто объект и известно, что он, действительно, будет нужен.

В этом случае, смысла в дополнительном конструкторе нет. Более того, в том же Ext-e, например, люди пишут, опять же, в Java-Swing-стиле: именно для организации наследования создают наследника от какого-то базового "класса", даже, если затем этот наследник породит всего _один_ объект. Спрашивается, зачем конструктор? Для наследования. Из-за этого приходится его плодить. Если бы можно было по стандарту (а не только через __proto__ в конкретных реализациях) менять свободно прототип, то пункт с наследованием бы отпал, конструктор был бы не нужен (как, кстати, и new).

Kolyaj 06.10.2009 19:19

Цитата:

Сообщение от Dmitry A. Soshnikov
Но терминологию "Синглтон" и этот паттерн (при той же организации) можно и не использовать.

Ну не придумывать же новый термин.

Dmitry A. Soshnikov 06.10.2009 20:29

Цитата:

Сообщение от Kolyaj
Ну не придумывать же новый термин.

Да нет же, вот пример с геттером для this.panel из примера выше - разве ты это называешь "Синглтоном"? Технически-то понятно, что и там (паттерн "Синглтон"), и там (memoization, кэш) - возвращается один объект, но идеология-то разная.

Повторю, в ответе на Хабре имелся в виду обычный объект, который однозначно будет использоваться (и в этом плане, конструктор - лишний). Более того, если уж приплетать терминологию "Синглтон", можно и этот объект назвать "Синглтоном" (а чем он отличается от того, который будет порождён альтернативным конструктором?).

Но, опять повторюсь, чем можно оправдать наличие конструктора для одиночного объекта - это (1) наследование (и, как пример, я привожу идеологию ExtJS и её обёртку наследования - когда для одной панели нужно объявить "класс") и (2) - геттер для частых проверок.

Kolyaj 06.10.2009 20:33

Цитата:

Сообщение от Dmitry A. Soshnikov
чем можно оправдать наличие конструктора для одиночного объекта

В моем случае цели декоративные.
var S = {
// много строк кода
};

// А вот тут уже инициализация объекта
Такой код читается хуже, чем
var S = Singleton({ // <-- псевдокод
    init: function() {
        // инициализация
    },
    // остальной код
})

Kolyaj 06.10.2009 20:47

Цитата:

Сообщение от Dmitry A. Soshnikov
getPanel: function () {
  if (!this.panel) {
    // вычисления и создание панели
  }
  return this.panel;
}

Это не синглтон, для разных объектов панель будет разная.

Dmitry A. Soshnikov 06.10.2009 20:59

Цитата:

Сообщение от Kolyaj
Это не синглтон

Так в вопросе о множественных проверках (if-aх, else-ах), я о чём и говорю - это можно не называть "Синглтоном". Это геттер, который, одним из действий, выполняет инициализацию.


Часовой пояс GMT +3, время: 19:55.