JavaScript Паттерны #1 - Singleton (Одиночка)

Поділитися
Вставка
  • Опубліковано 1 жов 2024
  • #YauhenK #webDev #JS #JSPatterns
    Всех приветствую в курсе «JavaScript Паттерны».
    В данном видео-курсе мы с вами рассмотрим самые распространённые паттерны проектирования, которые используются при разработке.
    Паттерны, или шаблоны - это определённые, зарекомендовавшие себя конструкции, которые служат для решения типовых задач программирования.
    Рассматривать мы их с вами будем на примере языка JavaScript в синтаксисе ES6.
    ✒ Репозиторий курса:
    ✔ GitHub: github.com/Yau...
    ✒ Используемые ресурсы и инструменты:
    ✔ Carbon (Screenshots): carbon.now.sh/
    ✒ Полезные ссылки:
    ✔ ES6: • ES6
    ✒ Полный список готовых и планируемых курсов:
    ✔ Trello: trello.com/b/R...
    ✒ Автор курса:
    ✔ UA-cam: / yauhenkavalchuk
    ✔ Instagram: / yauhenkavalchuk
    ✔ Twitter: / yauhenkavalchuk
    ✔ VK: YauhenK...
    ✔ LinkedIn: / yauhenkavalchuk
    ✔ GitHub: github.com/Yau...
    ✔ VK (Группа): webdevcom
    ✒ Поддержать развитие канала: github.com/Yau...

КОМЕНТАРІ • 116

  • @ИмяФамилия-э4ф7в
    @ИмяФамилия-э4ф7в 4 роки тому +23

    Некоторые спрашивают, зачем это нужно на практике? Приведу свой пример: есть класс, инкапсулирующий работу с хранилищем firebase. Снаружи он реализует интерфейс типа "дай то", "дай это", "запиши то", "запиши это". Внутре же он инициализирует соединение с базой данных, содержит данные конфигурации и путей, преобразует хотелки в конкретные запросы согласно API. Так вот, не желательно при наличии созданного подключения пытаться создать его заново. Не критично, но и не желательно.
    Вся история происходит в React, сервер могут пинать разные компоненты из разных мест, каждому из них нужна ссылка на экземпляр класса, они его получают через import. Мне хотелось бы гарантировать, что соединение будет инициализированно один раз. Запилил singletone, и не парюсь, один раз прочитает webpack импорты, или не один.

    • @eugenenovikov671
      @eugenenovikov671 2 роки тому +2

      это только пишущим на react надо объяснять что такое синглтон, у нас в ангуляре все сервисы синглтоны

    • @Sergey_Klimov
      @Sergey_Klimov 3 місяці тому +1

      ​@@eugenenovikov671да умница, возьми с полки пирожок.

    • @eugenenovikov671
      @eugenenovikov671 3 місяці тому

      @@Sergey_Klimov долго думал что бы написать такое?

    • @Sergey_Klimov
      @Sergey_Klimov 3 місяці тому

      @@eugenenovikov671 нет. Аналогичный вопрос и тебе, чсвшный ангулярщик

    • @eugenenovikov671
      @eugenenovikov671 3 місяці тому

      @@Sergey_Klimov ммм подгорело, понимаю.

  • @freedom_twin
    @freedom_twin 4 роки тому +12

    instance.count = 0 наверное должен быть в блоке if, иначе он каждый раз будет обнулять счетчик?(3:22)

    • @ИмяФамилия-э4ф7в
      @ИмяФамилия-э4ф7в 4 роки тому +3

      Полез в комменты написать это. А тут ты )).

    • @mitrasu5918
      @mitrasu5918 2 роки тому

      @@ИмяФамилия-э4ф7в я такаяже хуйня

  • @everdimension
    @everdimension 4 роки тому +5

    Спасибо за видео и старания. Но даже оставив вопрос о том, где этот паттерн может быть полезен, скажу, что вот такие видео в контексте js порождают только больше непонимания относительно паттернов проектирования. В js нет никакого смысла создавать синглтон описанным в видео способом. ES-модули являются синглтонами сами по себе. Достаточно создать файл и экспортировать желаемый объект или методы. Вот и весь "синглтон". А трюки со статическим полем instance нужны только в джаве.

    • @YauhenKavalchuk
      @YauhenKavalchuk  4 роки тому

      И тем не менее, Singleton- это отдельный паттерн, который вполне резонно попал в этот курс. Но на счёт модулей, абсолютно согласен

    • @everdimension
      @everdimension 4 роки тому +3

      ​@@YauhenKavalchuk Я согласен, что паттерн не стоит обходить стороной. Проблема на мой взгляд в том, что почти во всех материалах, рассказывающих об этих паттернах, за кадром остаётся главное - мотивация. Когда именно они уместны. Но реальные примеры никто не приводит. Лишь абстрактные советы (бездушное "адаптер полезен, когда вам нужно использовать имеющийся класс для клиента, ожидающего другой интерфейс") или с головой погружения в "заводы для бмв".

    • @alehmakaranka1089
      @alehmakaranka1089 4 роки тому

      Блин, точняк

  • @pcaptanovsky
    @pcaptanovsky 9 місяців тому +1

    проблема такой реализации, что свойство instance никак не защищено, и если после создания первого экземпляра класса и перед созданием второго присвоить null свойству Counter.instance, то второй экземпляр получит ссылку на пустой объект.
    а можно и другой объект туда передать, со своими свойствами и переписанными методами, которые при вызове будут делать уже совсем не то, что мы планировали.

  • @O_Hat
    @O_Hat 2 роки тому +1

    Я понял, сначала нужно ставить дизлайк, па потом лайк

  • @rusnickk
    @rusnickk 5 років тому +3

    Спасибо за видео, к 3:30 вопрос каждый новый вызов конструктора будет сбрасывать счётчик, думаю инициализация count должна быть в ветке if и отрабатывать ровно один раз если !instance?

    • @YauhenKavalchuk
      @YauhenKavalchuk  5 років тому

      В целом да, можно и так сделать.

  • @gtdsafafasf
    @gtdsafafasf 4 роки тому +2

    По сути в JS если просто объявить переменную в глобальной области, скажем: let counter = 0; и просто обращаться к ней из разных точек программы то это уже singleton ? Зачем мы вообще используем класс Counter для реализации этого паттерна ? Что бы снабдить доступ к переменной instance внешним удобным интерфейсом ? Есть ли еще причины, по которым мы используем класс ?

    • @ИмяФамилия-э4ф7в
      @ИмяФамилия-э4ф7в 4 роки тому

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

    • @andrewklochko340
      @andrewklochko340 2 роки тому

      А если понадобится создать ограничение, допустим счётчик не должен быть меньше нуля? Если переменная будет глобальная, её можно вертеть как хотеть. Работая через методы можно сделать проверку, а в случае неверных значений предпринять какие-то действия (вернуть ошибку, предупреждение, поставить дэфолтное значение)

  • @АндрійКирієнко-х2ь
    @АндрійКирієнко-х2ь 5 років тому +2

    спасибо за видео, но я так и не понял ( + запутался ) примерное назначение етого паттерна... если объекты разные (false) то ето потому что они совсем 2 чужих объекта, если надо сделать (true) то надо сохранить силку объекта в другой переменой и сравнивать, и не надо юзать конструкцию класса и методов

    • @s_bandera
      @s_bandera 5 років тому +2

      Говорить научись, потом вопросы формулировать, а потом вопрошай.

  • @NewDimix
    @NewDimix 5 місяців тому

    Не понял с каких пор и по каким причинам синглтон стал антипаттерном? Вот это интересно было бы послушать

  • @andriidou8023
    @andriidou8023 5 років тому +2

    код в RunJS вроде написан, класная вещь если хочется что-то затестить в js а разворачивать среду лень, туда даже либы можно импортить, Крч всем советую поставить и попробовать

    • @mustapha_mond
      @mustapha_mond 5 років тому

      спасибо за комментарий, дельная штука!

  • @Sergey_Klimov
    @Sergey_Klimov 3 місяці тому

    Тогда непонятно зачем создавать новый экземпляр класса к каждой переменной. Ну был бы это export default обычный и все.

  • @dezo103
    @dezo103 4 роки тому +4

    Спасибо за курс, но мне как новичку не понятно)))

    • @YauhenKavalchuk
      @YauhenKavalchuk  4 роки тому +3

      Вам, как новичку, я бы не рекомендовал лезть в этот курс. И для начала подтянуть основы

    • @GonzaVladimir
      @GonzaVladimir Рік тому

      я с небольшим опытом , и то думаю применить не применить и забываю что то и лезу тоже в такие курсы и мне тоже не сразу понятно =))))) один раз пока я применял синглтон

  • @АйдынГалымжанулы
    @АйдынГалымжанулы 6 місяців тому

    Насколько я понял это похоже на vuex, pinia, redux и тд

  • @codeforgames
    @codeforgames Рік тому

    Я все же пришел к проверке такого типа:
    if (Singleton.instance instanceof Singleton) return Singleton.instance;
    Более правильная, на мой взгляд)
    Если короче, то вообще if (Singleton.instance ) return Singleton.instance;

  • @qazyhn94
    @qazyhn94 5 років тому +2

    вопрос такой, если мы используем require или import модули из ES6, вот этот самый require читает файл один раз во время жизни программы, тоесть если мы делаем export default new Singleton() в файле модуля, всегда когда я буду делать import в коде я получу один и тот же обьект, что по сути и есть синглтон благодаря модулям, есть ли какие то минусы у такого подхода?

    • @YauhenKavalchuk
      @YauhenKavalchuk  5 років тому +1

      Нет. Просто это не нативная реализация, а реализация с помощью сборщика

    • @lizzienovigot
      @lizzienovigot 5 років тому +1

      Мне кажется это лучше реализация. Описанная в видео плоха тем что пользователь может создавать "разные" экземпляры не понимая что они есть один и тот же обьект. Это может легко привести к багам.

    • @ИмяФамилия-э4ф7в
      @ИмяФамилия-э4ф7в 4 роки тому

      Разница в том, что require или import это инструкции сборщика, а не часть языка JS (пока, во всяком случае). А он читает один раз, но НЕ ГАРАНТИРУЕТ, что чтение будет произведено ровно один раз. В принципе, из каких-либо своих соображений, он может прочитать пару раз. Или завтра реализацию переделают. Ставить свой код в зависимость от таких факторов - не лучшая идея.

  • @irynabelaya8191
    @irynabelaya8191 3 роки тому +2

    Про синглтон: а как это будет реализваться в объекте, на основе созданного класса? То есть в новом объект будет свойство instance (или что это будет?)? И каким образом нам ссылаться из нового объекта на функцию-конструктор? И зачем нам может понадобиться ссылаться на функцию -конструктор?

    • @Sergey_Klimov
      @Sergey_Klimov 3 місяці тому

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

  • @deadhead7303
    @deadhead7303 8 місяців тому

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

  • @RK-gm4pd
    @RK-gm4pd 4 роки тому

    WTF вопросов больше, чем полученного материала!
    "обьект, которий есть в одном єкземпляре" - обьект, как обьект ООП, не JS object literal, потому как последний по определению в одном єкземпляре, потому как реферальний тип. И об єтом в видео сказано. Зачем переписивать { obj } в Class что би потом через instance получить доступ к свойствам и методам, которие уже есть в obj _proto_ ? Зачем создавать два "разних" instance, чтоби потом обратиться к тому же свойству того же обьекта?
    "и к которому может бить доступ из разних частей программи". вот тут вобще не понял! если ми создаем глобальную переменную, то как к ней не может бить достпа? И отсюда опять вопрос: "Глобальная переменная єто хорошо нам, или плохо?" Модульная система предотвращает доступ к глобальним переменним извне приложения, а необходимость глобальних переменних диктуется архитектурой приложения. Значит ли єто, что Синглтон вместе с ООП идут лесом?
    в ES модульной системе нельзя импортировать и мутировать переменую саму по себе:
    // ES module Singlton.js
    export let Global = 0;
    // app.js
    import { Global } from 'Singlton.js' ;
    console.log(Global); // 0
    Global = Global++; // TypeError: can't assign to 'Global' because it's not a variable or Assignment to constant variable.
    потому как модуль/файл заворачивается в IIFE (тоже упомянуто в видео), и потому: Синглтон от ООП - снова в сад! А по природе JS на сегодня - "синглтон"для глобальной переменной не минуем на корню:
    // ES module Singlton.js
    let Global = 0;
    export const increaseGlobal = () => {
    Global++;
    }
    export const getGlobal = () => {
    return Global;
    }
    // app.js
    import { getGlobal, increaseGlobal } from 'Singlton.js';
    let Global = getGlobal();
    console.log(Global); // 0
    increaseGlobal();
    Global = getGlobal();
    console.log(Global); // 1
    increaseGlobal();
    Global = getGlobal();
    console.log(Global); // 2
    ...

  • @Daddar2253
    @Daddar2253 3 роки тому

    подскажите, так как мы используем new для получения синглтона, то по идее каждый раз, когда мы ходим взять созданный инстанс, мы все равно выделяем память для создания пустого Counter (хоть и в конструкторе подменяем на инстанс). ок ли это?
    в теории можно создать статичный метод у класса (или функцию с замыканием), тогда такой проблемы не будет

  • @Fodintsov
    @Fodintsov 2 роки тому +3

    Можно просто создать класс со static-методами и static-переменными. Тоже синглтон. :)

  • @arman-6172
    @arman-6172 2 роки тому

    Голова бобо с такого =)
    $counter1 = new Counter();
    $counter2 = new Counter();
    $counter1 === $counter2 // true
    Кроме JS где-то еще можно так? Как-то больше через статику видел. Может это нюанс JS и не стоит на нем пример паттерна показывать? или это общая практика в JS? Тут я больше про реализацию паттерна в конструкторе.

  • @nataliashiryaeva5259
    @nataliashiryaeva5259 4 роки тому

    зачем глобальная переменная и при чем здесь синтаксис ES6? Это же статическое свойство вы добавляете (без ключевого слова). И зачем проверка на object?
    Вот такая конструкция решает проблему во всех синтаксисах:
    if (!Count.instance) Count.instance = this;
    else return Count.instance;
    подход тот же - если объект уже существует, то не создавай новый, а верни старый.
    (И возвращать this не нужно, конструкторы это неявно делают.)
    я не придираюсь :) Просто не вижу слабые места в указанной мной конструкции

    • @ИмяФамилия-э4ф7в
      @ИмяФамилия-э4ф7в 4 роки тому

      Else не нужен. Так как ты написала, мы проверяем, существует ли instance, и если да, то возвращаем его. Если же нет, то создаём его и полагаемся на возврат конструктором this.
      Если же написать всё то же самое, но без else, то мы будем проверять, есть ли instance, если нет, то создавать его, и всегда возвращать instance. Разницы, вроде, нет особо. Что приходит на ум, а может ли this при каких нибудь условиях != instance? Понятно, что не в данном примере.

  • @BrainProletarian
    @BrainProletarian 3 роки тому

    4:53 "Мы сохранили ссылку на экземпляр в статическом свойстве конструктора" - не правильнее было сказать "Сохранили ссылку на экземпляр в статическом свойстве нашего класса-функции", т.к. по тексту возникает двусмысленность из-за наличии в классе функции "constructor"?

  • @zerdox4
    @zerdox4 4 роки тому

    почему ты говоришь что instance - глобальная переменная, если в джаваскрипте глобальные переменные это свойства глобального объекта?

    • @YauhenKavalchuk
      @YauhenKavalchuk  4 роки тому

      Прочитайте по терминологии JS и всё поймёте

  • @pupizoid100
    @pupizoid100 Рік тому

    А через сингл паттерн можно реализовать функцию, чтоб на одной странице проигрывалось только одно видео с ютуба из всех остальных?

  • @gitarmengitarmenovich767
    @gitarmengitarmenovich767 4 роки тому

    @webDev , спасибо за курс, все понятно. Попробовал реализовать этот паттерн на примере корзины, и как-то запутался..., реализовал подключение корзины в родительском компоненте, и в дочерних обращался к нему, но все же если импортировать этот же класс в дочернем и вызвать его конструктор, то он перестает быть синглтоном
    import Basket from './basket'
    class Parent {
    static basket = null
    prepare() {
    this.basket = new Basket()
    }
    }
    class Child extends Parent{
    prepare() {
    super.prepare()
    this.basket.addProduct('item')
    this.basket.getProducts()
    let newInstance = new Basket()
    newInstance.getProducts() //Новый экземпляр
    }
    }
    Код корявые наброски(прошу не критиковать)), но все же, можно как-то сделать чтоб даже при импорте класс в проекте оставался синглтоном, без создания прослойки?

  • @_kie
    @_kie 5 років тому +1

    Так у класса или у объекта - в определении этого паттерна именно объект? Потому что начал ты с объекта, а закончил классом. Решил посмотреть еще какую-нибудь статью по теме, открыл Медиум, там тоже начинается с объекта, потом, внезапно, идёт про класс. WTF?

    • @raptorthefirst
      @raptorthefirst 5 років тому

      Так что тебе мешает переписать это под объект ?

    • @raptorthefirst
      @raptorthefirst 5 років тому

      Ну тип function Singleton() {..}
      Почти ничего не меняется. Когда вызываешь конструктор через new, то тип можно просто прописать в начале условие, что если объект существует, ссылаться на него. Изи

    • @raptorthefirst
      @raptorthefirst 5 років тому

      let instance;
      -class Singleton{
      - constructor(){
      - if(!instance) instance = this;
      +function Singleton(){
      +
      + if(!instance) instance = this;
      + else{
      instance.count = 0;
      return instance;
      }
      -
      - showCount(){
      +
      + this.showCount = function(){
      console.log(instance.count);
      }
      - increaseCount(){
      + this.increaseCount = function(){
      return instance.count++;
      }
      }
      +
      let car1 = new Singleton;
      let car2 = new Singleton;
      git push youtube Лови )))

    • @YauhenKavalchuk
      @YauhenKavalchuk  5 років тому +8

      Под капотом, классы в JS являются объектами. Классов в «классическом» смысле не существует.

  • @Developer-u7o
    @Developer-u7o 2 роки тому

    Спасибо, объяснили четко и ясно, я правильно понял, синглтон - это что-то в единственном экземпляре, я люблю аналогию, и можно ли синглотн сравнить с рулем от автомобиля? Руль - является синглотоном, но при этом на него могут влиять другие части, допустим: рулевая рейка, поворот колес, без использования руля и т.п. Т.е синглтон это что-то единственное в своем роде. Допустим есть список песен, я делаю запрос, получаю музыку, слушаю ее, переключаю и тд - это всё объекты и данные, а вот плеер, который есть на моей странице - это синглтон, правильно ли рассуждаю?

    • @YauhenKavalchuk
      @YauhenKavalchuk  2 роки тому +1

      Вроде как рассуждения верны

  • @flockast
    @flockast 3 роки тому

    Спасибо за видео! Подскажите пожалуйста, подобную реализацию модуля можно назвать singleton? Ведь при подключении мы получаем один и тот же instance.
    class Counter {
    constructor () {
    this.count = 0
    }
    ...
    }
    export default new Counter()

  • @glucus2274
    @glucus2274 2 роки тому

    Иными словами Store == Singleton

  • @sargernax
    @sargernax 5 років тому +3

    Да супер ваще )))

    • @YauhenKavalchuk
      @YauhenKavalchuk  5 років тому

      Спасибо за отзыв!

    • @sargernax
      @sargernax 5 років тому

      @@YauhenKavalchuk К сожалению пока нет денег, с удовольствием заплатил бы вам за уроки.

  • @yevheniimoskalenko1624
    @yevheniimoskalenko1624 3 роки тому +1

    Спасибо, понял только на практике)

  • @dmitriifisenko6069
    @dmitriifisenko6069 2 роки тому

    них...я не понял но очень интересно!

  • @JenechekDv
    @JenechekDv 4 роки тому

    Когда на собеседовании спрашиваю про паттерны лучше начинать с чего то другого)

    • @YauhenKavalchuk
      @YauhenKavalchuk  4 роки тому

      Почему?)

    • @JenechekDv
      @JenechekDv 4 роки тому

      @@YauhenKavalchuk Начинающие часто учат этот паттерн первым и на собеседовании сразу выдают его т.к. он один из самых простых. Сам так делал и более опытные коллеги говорят, что если человек начинает с одиночки, велика вероятность, что он только его и знает и надо уделить этой теме больше внимания.

  • @valeriyk7565
    @valeriyk7565 8 місяців тому

    Красава! Спасибо!

  • @nun8930
    @nun8930 5 років тому

    Автор у меня вопрос, стоит ли лезть во фронтенд без знания математики?
    Я правда залез немножко уже, и теперь возник этот вопрос, и не знаю, тратить ли свое время дальше.

    • @YauhenKavalchuk
      @YauhenKavalchuk  5 років тому +1

      Стоит, всё нормально

    • @eugenegavrilov2618
      @eugenegavrilov2618 5 років тому +4

      за несколько лет работы, только месяца 2 назад, первый раз понадобилась математика и геометрия

    • @nun8930
      @nun8930 5 років тому

      Благодарю за ответы

    • @ВиталийПетрушков-у8ф
      @ВиталийПетрушков-у8ф 4 роки тому

      Программирование намного больше похоже на физику чем на математику

  • @lizzienovigot
    @lizzienovigot 5 років тому +1

    Спасибо. Не задумывался что можно так сделать хоть и знал про такое поведение конструктора существует. Всегда удивлялся зачем такое правило)))

  • @jocoders6175
    @jocoders6175 5 років тому

    Красавелла!

  • @oOIMAXIOo
    @oOIMAXIOo 5 років тому +2

    Не совсем понял зачем он нужен, если корзину можно просто запихнуть в localstorage и иметь доступ кней с любой страницы?

    • @qazyhn94
      @qazyhn94 5 років тому +1

      А если мы пишем на Node? ))

    • @andriidou8023
      @andriidou8023 5 років тому

      1. LocalStorage не для этого придуман
      2. В некоторых браузерах в режиме инкогнито недоступен localStorage соответственно апка будет не рабочая
      3. А если у тебя будет 10 -15 синглтонов ты будешь их все на старте через JSON.stringify() перегонять и писать в localStorage а затем через JSON.parse() доставать. Звучит тупо согласись.

    • @YauhenKavalchuk
      @YauhenKavalchuk  5 років тому +1

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

    • @oOIMAXIOo
      @oOIMAXIOo 5 років тому

      @@andriidou8023 Искренне надеюсь ты нескем не общаешься с людьми кроме как со мной! Манера общения у тебя как высокомерного дегенерата, тебя бы закрыть в комнате со своими фотками и своим кодом...

    • @oOIMAXIOo
      @oOIMAXIOo 5 років тому

      @@YauhenKavalchuk Да я уверен просто не сталкивался еще с таким родом проблем, поэтому и спросил когда и зачем он нужен!)

  • @s_bandera
    @s_bandera 5 років тому

    Да уж, сейчас бы паттерны на js учить в 2к19....

  • @АлександрМарков-э2б

    Спасибо, всё наглядно и понятно

  • @dmitrykorovin4356
    @dmitrykorovin4356 3 роки тому

    доходчиво, спасибо за видео

  • @КостянЕрмаков-е9ю
    @КостянЕрмаков-е9ю 5 років тому

    градиент привлекает внимание больше чем код на темном фоне. Глаз начинает дергаться от напряжения, ну, это у меня так, по крайней мере.

    • @YauhenKavalchuk
      @YauhenKavalchuk  5 років тому

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

    • @КостянЕрмаков-е9ю
      @КостянЕрмаков-е9ю 5 років тому +4

      @@YauhenKavalchuk, ладно, будем монитор скотчем обклеивать тогда по периметру🤣