Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску
Диаграмма классов, иллюстрирующая одноэлементный паттерн.

В программной инженерии , то шаблон одноточечно является шаблоном проектирования программного обеспечения , что ограничивает создание экземпляра в виде класса к одному «единым» , например. Это полезно, когда требуется ровно один объект для координации действий в системе. Термин происходит от математической концепции синглтона .

Критики считают синглтон анти-шаблоном в том смысле, что он часто используется в сценариях, где он нецелесообразен, вводит ненужные ограничения в ситуациях, когда единственный экземпляр класса фактически не требуется, и вводит глобальное состояние в приложение. [1] [2] [3] [4]

Обзор [ править ]

Шаблон проектирования singleton [5] - это один из двадцати трех хорошо известных шаблонов проектирования «Банда четырех», которые описывают, как решать повторяющиеся проблемы проектирования для разработки гибкого и многократно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые проще в использовании. внедрять, изменять, тестировать и повторно использовать.

Шаблон проектирования singleton решает такие проблемы, как: [6]

  • Как можно гарантировать, что у класса есть только один экземпляр?
  • Как можно легко получить доступ к единственному экземпляру класса?
  • Как класс может управлять созданием своего экземпляра?
  • Как можно ограничить количество экземпляров класса?
  • Как получить доступ к глобальной переменной?

Шаблон проектирования singleton описывает, как решать такие проблемы:

  • Скройте конструктор класса.
  • Определите общедоступную статическую операцию ( getInstance()), которая возвращает единственный экземпляр класса.

Ключевая идея в этом шаблоне - сделать сам класс ответственным за управление его экземпляром (что он создается только один раз).
Скрытый конструктор (объявленный как частный ) гарантирует, что класс никогда не может быть создан извне.
Доступ к общедоступной статической операции можно легко получить, используя имя класса и имя операции ( Singleton.getInstance()).

Обычное использование [ править ]

  • Абстрактная фабрика , Фабричный метод , строитель и прототип модели могут использовать одиночка в их реализации.
  • Фасадные объекты часто бывают одиночными, потому что требуется только один фасадный объект.
  • Государственные объекты часто бывают одиночными.
  • Синглтоны часто предпочтительнее глобальных переменных, потому что:
    • Они не загрязняют глобальное пространство имен (или, в языках с вложенными пространствами имен, содержащее их пространство имен) ненужными переменными. [5]
    • Они допускают отложенное выделение и инициализацию, тогда как глобальные переменные во многих языках всегда потребляют ресурсы.

Соображения, касающиеся антипаттернов [ править ]

Шаблон Singleton обычно считается "анти-шаблоном" по следующим причинам:

Одноэлементные классы нарушают принципы объектно-ориентированного проектирования [ править ]

  1. Он не может быть унаследован от . Чтобы добавить новую функциональность, новый класс не может быть наследником, чтобы содержать эту функциональность, нарушая разделение проблем.
  2. Нет контроля над созданием . Невозможно сказать, относится ли ссылка к существующему экземпляру или новому экземпляру.
  3. Предотвращает внедрение зависимостей . Поскольку существует только один экземпляр класса, зависимость не может быть введена в него. Если это сделано через свойство, зависимость изменяется для всех ссылок на этот экземпляр.

Одноэлементные классы не допускают разработки через тестирование (TDD). [ редактировать ]

  1. Поскольку нет контроля над созданием, «чистый» экземпляр объекта не может использоваться для каждого теста.
  2. Без внедрения зависимостей фиктивные объекты нельзя использовать в тестах.

Реализация [ править ]

Реализация одноэлементного шаблона должна:

  • убедитесь, что когда-либо существует только один экземпляр одноэлементного класса; и
  • предоставить глобальный доступ к этому экземпляру.

Обычно это делают:

  • объявление всех конструкторов класса закрытыми ; и
  • предоставление статического метода , возвращающего ссылку на экземпляр.

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

public  final  class  Singleton  { частный  статический  финальный  синглтон  INSTANCE  =  новый  синглтон (); частный  синглтон ()  {} общедоступный  статический  синглтон  getInstance ()  {  return  INSTANCE ;  } }

Реализация Python [ править ]

class  Singleton :  __instance  =  None  def  __new__ ( cls ,  * args ):  if  cls . __instance  is  None :  cls . __instance  =  объект . __new__ ( cls ,  * args )  возвращает  cls . __пример

Реализация C # [ править ]

публичный  запечатанный  класс  Singleton {  публичный  статический  экземпляр Singleton  { получить ; } = новый синглтон ();       частный  синглтон ()  {  } }

В C # вы также можете использовать статические классы для создания синглтонов, где сам класс является синглтоном.

общедоступный  статический  класс  Singleton {  общедоступный  статический  экземпляр MyOtherClass  { получить ; } = новый MyOtherClass (); }      

Реализация Unity [ править ]

Синглтоны могут быть полезным инструментом при разработке с помощью Unity благодаря уникальному способу создания экземпляров классов. Этот метод предпочтительнее скрытия конструктора, поскольку в Unity можно создать экземпляр объекта с помощью скрытого конструктора.

Чтобы предотвратить перезапись экземпляра, необходимо выполнить проверку, чтобы убедиться, что экземпляр равен нулю. Если Instance не равен нулю, GameObject, содержащий вредоносный скрипт, должен быть уничтожен.

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

class  Singleton  :  MonoBehaviour {  общедоступный  статический  экземпляр Singleton  { получить ; частный набор ; }      private  void  Awake ()  {  if  ( Instance  ! =  null  &&  Instance  ! =  this )  {  Destroy ( this . gameObject );  }  else  {  Экземпляр  =  это ;  }  } }

Примечание. Также возможно реализовать, удалив только скрипт-нарушитель, а не GameObject, вместо этого вызывая Destroy (this);

Ленивая инициализация [ править ]

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

public  final  class  Singleton  { частный  статический  изменчивый  экземпляр Singleton  = null ;   частный  синглтон ()  {} общедоступный  статический  синглтон  getInstance ()  {  если  ( экземпляр  ==  нуль )  {  синхронизирован ( синглтон . класс )  {  если  ( экземпляр  ==  нуль )  {  экземпляр  =  новый  синглтон ();  }  }  } возвратный  экземпляр ;  } }

Реализация дротика [ править ]

class  Singleton  { Синглтон . _ (); статический  синглтон  получить  экземпляр  =>  синглтон . _ ();}

Реализация PHP [ править ]

класс  Синглтон{ частный  статический  $ instance  =  null ; частная  функция  __construct ()  {} публичная  статическая  функция  getInstance () :  self { if  ( null  ===  self :: $ instance )  { self :: $ instance  =  new  self (); } вернуть  self :: $ instance ; }}

Реализация Java [7] [ править ]

public  class  Coin  { частный  статический  final  int  ADD_MORE_COIN  =  10 ; приватная  внутренняя  монета ; частный  статический  экземпляр Coin  = new Coin (); // С нетерпением загрузка экземпляра синглтона     private  Coin () { // закрытый, чтобы никто другой не мог создать экземпляр } public  static  Coin  getInstance ()  { возвратный  экземпляр ; } public  int  getCoin ()  { вернуть  монету ; } public  void  addMoreCoin ()  { монета  + =  ADD_MORE_COIN ; } public  void  deductCoin ()  { монета - ; }}

Реализация Kotlin [7] [ править ]

Ключевое слово объекта Kotlin объявляет одноэлементный класс [8]

object  Coin  { частная  монета var  : Int = 0    fun  getCoin (): Int  { вернуть  монету } fun  addCoin ()  { монета  + =  10 } fun  deductCoin ()  { монета - }}

Реализация Delphi и Free Pascal [ править ]

GetInstance - это поточно-ориентированная реализация Singleton.

unit  SingletonPattern ;интерфейстип  TTest  =  класс  запечатанный  строгий  частный  FCreationTime :  TDateTime ;  публичный  конструктор  Create ;  свойство  CreationTime :  TDateTime  читать  FCreationTime ;  конец ;функция  GetInstance :  TTest ;выполнениеиспользует  SysUtils  ,  SyncObjs  ;var  FCriticalSection :  TCriticalSection ;  FInstance :  TTest ;функция  GetInstance :  TTest ; начать  FCriticalSection . Приобрести ;  попробуйте,  если  не  назначено ( FInstance ),  то  FInstance  : =  TTest . Создать ; Результат  : =  FInstance ;  наконец  FCriticalSection . Выпуск ;  конец ; конец ;конструктор  TTest . Создать ; begin  унаследовано  Create ;  FCreationTime  : =  Сейчас ; конец ;инициализация  FCriticalSection  : =  TCriticalSection . Создать ;доработка  FreeAndNil ( FCriticalSection ) ;конец .

Использование:

процедура  TForm3 . btnCreateInstanceClick ( Отправитель :  TObject ) ; var  i :  целое число ; begin  for  i  : = от  0  до  5  do  ShowMessage ( DateTimeToStr ( GetInstance . CreationTime )) ; конец ;

Заметки [ править ]

  1. ^ В Java, чтобы избежать накладных расходов на синхронизацию при сохранении ленивой инициализации с безопасностью потоков, предпочтительным подходом является использование идиомы инициализации по требованию держателя . [ необходима цитата ]

Ссылки [ править ]

  1. ^ Скотт Денсмор. Почему одиночки - зло , май 2004 г.
  2. ^ Стив Егге. Синглтоны считаются глупыми , сентябрь 2004 г.
  3. ^ Беседы о чистом коде - глобальное состояние и синглтоны
  4. ^ Максимилиано Контьери. Синглтон-паттерн: корень всего зла , июнь 2020 г.
  5. ^ a b Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес (1994). Шаблоны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования . Эддисон Уэсли. С.  127 и далее . ISBN 0-201-63361-2.CS1 maint: несколько имен: список авторов ( ссылка )
  6. ^ «Шаблон проектирования Singleton - проблема, решение и применимость» . w3sDesign.com . Проверено 16 августа 2017 .
  7. ^ a b «Вы разработчик Android и еще не используете класс Singleton?» .
  8. ^ "Объявления объекта" . Проверено 19 мая 2020 .

Внешние ссылки [ править ]

  • Полная статья « Объяснение паттерна Java Singleton »
  • Четыре различных способа реализации синглтона в Java « Способы реализации синглтона в Java »
  • Отрывок из книги: Реализация шаблона Singleton на C # от Джона Скита
  • Синглтон в Центре разработчиков шаблонов и практик Microsoft
  • Статья IBM Питера Хаггара " Двойная проверка блокировки и шаблон синглтона "
  • Статья IBM « Используйте свои одиночные игры с умом », автор: JB Rainsberger
  • Гири, Дэвид (25 апреля 2003 г.). «Как ориентироваться в обманчиво простом шаблоне Singleton» . Шаблоны проектирования Java. JavaWorld . Проверено 21 июля 2020 .
  • Статья Google " Почему синглтоны вызывают споры "
  • Google Singleton Detector (анализирует байт-код Java для обнаружения синглтонов)