Одинак (шаблон проєктування)

Одинак (англ. Singleton) — шаблон проєктування, належить до класу твірних шаблонів. Гарантує, що клас матиме тільки один екземпляр, і забезпечує глобальну точку доступу до цього екземпляра.

Через низку притаманних недоліків деякі розробники вважають його антипатерном або «душком» коду.

Мотивація

Для деяких класів важливо, щоб існував тільки один екземпляр. Наприклад, хоча у системі може існувати декілька принтерів, може бути тільки один спулер. Повинна бути тільки одна файлова система та тільки один активний віконний менеджер.

Глобальна змінна не вирішує такої проблеми, бо не забороняє створити інші екземпляри класу.

Рішення полягає в тому, щоб сам клас контролював свою «унікальність», забороняючи створення нових екземплярів, та сам забезпечував єдину точку доступу. Це є призначенням шаблону Одинак.

Недоліки

Одинак в об'єктно-орієнтованому програмуванні можна порівняти з глобальною змінною у процедурному програмуванні з відповідними недоліками[1][2].

Зокрема, цей шаблон створює неявні залежності між функціями та методами, які не декларуються в їхньому інтерфейсі[1][3].

Крім того, Одинак може створювати проблеми під час модульного тестування адже, на додачу до всього іншого, його важко замінити на фіктивну реалізацію (англ. mock)[1][4][5].

Ці та інші недоліки спонукали Еріха Гаму в інтерв'ю 2009 року визнати, що можливо він би відмовився від цього шаблону проєктування, адже вважає його використання одним із «душків» коду[1].

На думку Брайана Батона Одинак порушує один із принципів SOLID: принцип єдиної відповідальності, оскільки окрім власне бізнес логіки, на клас покладається відповідальність за виконання вимог до Одинака. Натомість, він пропонує виокремити функціональність Одинака в інший клас, наприклад, із використанням шаблону фабричного метода або абстрактної фабрики[6].

Деякі з перелічених вад можна позбутись застосуванням шаблону впровадження залежностей та принципу інверсії залежностей[1].

Застосування

Слід використовувати шаблон Одинак коли:

  • повинен бути тільки один екземпляр деякого класу, що легко доступний всім клієнтам;
  • єдиний екземпляр повинен розширюватись шляхом успадкування, та клієнтам потрібно мати можливість працювати з розширеним екземпляром не змінюючи свій код.

Структура

Діаграма класів, що описує структуру шаблону проєктування Одинак
  • Singleton — одинак:
    • визначає операцію Instance, котра дозволяє клієнтам отримувати доступ до єдиного екземпляру. Instance — це операція класу;
    • може нести відповідальність за створення власного унікального екземпляру.

Відносини

Клієнти отримують доступ до єдиного об'єкта класу Singleton лише через його операцію Instance.

Реалізації

Реалізації на C++

// Заголовний файл (.h)
//
// Ниттєбезпечна реалізація Одинака
//
// Ця версія виглядає оманливо просто, проте вона має застереження:
// - Перше, якщо одинак міститься в якійсь бібліотеці. Ті, хто використовуватимуть цю бібліотеку
// матимуть екземпляр одинака протягом роботи застосунка, незалежно
// від того, чи використовується він чи ні.
//
// - Друге, це випадок статичних залежностей файлів. Наприклад, уявімо що
// Singleton є якоюсь абстрактною фабрикою для типа BaseType, і
// застосовується метод create. Оскільки порядок ініціалізації статичних змінних
// протягом трансляції модулів не визначений, це може призвести
// до доступу до Одинака до моменту його конструювання, іншими словами
// до невизначеної поведінки, що є погана річ.
//
// namespace { const BaseType * const fileStaticVariable = Singleton::getInstance().create(); }
//
class Singleton
{
private: 
  static Singleton _instance;
 
  Singleton() {}
  ~Singleton() {} 	 
  Singleton(const Singleton &);	 
  Singleton & operator=(const Singleton &);
 
public:
  static Singleton& getInstance();
};
 
// Джерельний файл (.cpp)

// Ініціалізація статичного члена.
Singleton Singleton::_instance;

Singleton& Singleton::getInstance()
{
 return _instance;
}

Одинак Маєрса

Так званий «Одинак Маєрса» покладається на запроваджені у версії C++11 гарантії ниттєбезпечного ініціалізації статичної змінної в тілі методу[7]. Таким чином, простий та ниттєбезпечний Одинак в реалізації Скота Маєрса (англ. Scott Meyers) виглядає так:[1]

#ifndef SINGLETON_H_
#define SINGLETON_H_
class Singleton final {
public:
  // Метод повертає посилання на єдиний екземпляр класу, який зберігається
  // в локальній статичній змінній
  static Singleton& getInstance() {
    // єдиний екземпляр цього класу зберігатиметься у локальній статичній змінній
    // на противагу попередньому прикладу, ініціалізація екземпляру гарантовано
    // відбудеться тільки під час першого виклику цього метода (ліниво). Тобто,
    // якщо цей метод ніколи не буде викликаний, то і екземпляр не буде створено
    static Singleton theInstance { };
    return theInstance;
  }
private:
  Singleton() = default;
  Singleton(const Singleton&) = delete;
  Singleton(Singleton&&) = delete;
  Singleton& operator=(const Singleton&) = delete;
  Singleton& operator=(Singleton&&) = delete;
  // ...
};
#endif

Окрім нього, існують й інші варіанти шаблону Одинак без деяких його недоліків[8].

Реалізації на Java

Базовими засобами мови

Enum singleton, починаючи з Java 1.5:

public enum SingletonEnum {  
   INSTANCE;  
}

Проста реалізація зі створенням об'єкта під час завантаження його класу[9]

 public class Singleton {
   private Singleton(){}  
   private static final Singleton instance = new Singleton();
   public static Singleton getInstance() {
     return instance;
   }
 }

Реалізація з відкладеним (ледачим) створенням об'єкта за потреби із синхронізацією для багатопоточної безпеки[9]

 public class Singleton {
   private Singleton(){}  
   private static Singleton instance;
   public static synchronized Singleton getInstance() {
      if (instance==null) {
        instance = new Singleton();
      }
     return instance;
   }
 }

Реалізація з відкладеним (ледачим) створенням об'єкта за потреби, яка є багатопоточно безпечною, використовується шаблон Initialization on demand holder. Проблемою реалізації є те, що коли виникає помилка з киданням винятку під час виконання статичної ініціалізації, клас не завантажується і екземпляр одинака більше неможливо створити.

 public class Singleton {
   private Singleton() {}

  private static class SingletonHolder {
    private static final Singleton instance = new Singleton();
  } 

   public static Singleton getInstance() {
     return SingletonHolder.instance;
   }
 }

Бібліотечними засобами

Якщо система розподілена, кожна JVM може мати свій екземпляр Одинака. У EJB 3.1 з'явилась анотація @Singleton, яка забезпечує унікальність Одинака на різних JVM[10]

@Singleton
public class SingletonA { 
}

За допомогою аспектів

Особливістю реалізації засобами мови програмування є необхідність для клієнта використовувати не конструктор, а фабричний метод для одержання об'єкта.

За допомогою засобів аспектно-орієнтованого програмування можна зробити реалізацію Одинака з використанням конструктора.

Реалізація за допомогою AspectJ [11]

 public abstract aspect AbstractSingletonAspect {
   private Object singleton = null;
   abstract pointcut singletonPointcut();
   Object around(): singletonPointcut() {
     if (singleton == null) {
       singleton = proceed();
     }
     return singleton;
   }
 }

 public aspect SingletonAspect extends AbstractSingletonAspect {
   pointcut singletonPointcut() : call(Stats.new(..));
 }

Реалізація за допомогою JBoss AOP[11]. Код аспекта:

 package aop.patterns.singleton;
 import org.jboss.aop.advice.Interceptor;
 import org.jboss.aop.joinpoint.Invocation;
 
 public class SingletonInterceptor implements Interceptor {
   private Object singleton;
   public Object invoke(Invocation invocation) throws Throwable {
     if (singleton==null) {
       singleton = invocation.invokeNext();
     }
     return singleton;
   }
 }

Конфігурація у jboss-aop.xml

 <bind pointcut="execution(aop.patterns.singleton.Singleton-&gt;new())">
   <interceptor class="aop.patterns.singleton.SingletonInterceptor" />
 </bind>

Реалізація на Actionscript 3.0

package {
	public class Singleton  {
		
		private static var _instance:Singleton = new Singleton();

		public function Singleton () {	
	            if (_instance){
		        throw new Error( 
                            "Singleton can only be accessed through Singleton.getInstance()" 
                        );
                    }
		}
		
		public static function getInstance():Singleton {
			return _instance;
		}

	}
}


Реалізація на Ruby

Мова програмування Ruby має вбудовану підтримку деяких шаблонів[12], зокрема й Одинака.

Модуль Singleton з бібліотеки singleton робить конструктор приватним та надає фабричний метод.

 require 'singleton' 

 class MyClass 
   include Singleton 
 end 

 a = MyClass.instance

Реалізація на Scala

У Scala шаблон підтримується засобами мови:

object Singleton

// Використання:
val singleton = Singleton

Реалізація на Smalltalk

Реалізація на Smalltalk [13]:

new
    self error: 'cannot create new object'

default
    SoleInstance isNil ifTrue: [SoleInstance := super new].
    ^ SoleInstance


Реалізація на PHP5

Реалізація на PHP

<?php
class Singleton {
  // object instance
  private static $instance;
 
  private function __construct() {}
 
  private function __clone() {}
 
  public static function getInstance() {
    if (self::$instance === null) {
      self::$instance = new self;
    }
    return self::$instance;
  }
 
  public function doAction() {
    ...
  }
}
 
//usage
Singleton::getInstance()->doAction();
?>

Реалізація на Delphi

Для Delphi 2005 та вище підходить наступний приклад:

type
  TSingleton = class
  strict private
    class var
      Instance: TSingleton;
  public
    class function NewInstance: TObject; override;
  end;

class function TSingleton.NewInstance: TObject;
begin
  if not Assigned(Instance) then
    Instance := TSingleton(inherited NewInstance);
  NewInstance := Instance;
end;

Для більш ранніх версій треба перемістити код класу до окремого модулю, а оголошення Instance замінити оголошенням глобальної змінної в його секції implementation (до Delphi 7 включно секції class var та strict private були відсутніми).

Примітки

  1. а б в г д е Stephan Roth (2017). The Singleton Anti-Pattern. Clean C++. Apress. doi:10.1007/978-1-4842-2793-0. ISBN 978-1-4842-2792-3.
  2. Jim Hyslop, Herb Sutter (1 березня 2003). Once Is Not Enough. Dr. Dobbs Joural.
  3. Miško Hevery (17 серпня 2008). Singletons are Pathological Liars. Google Testing blog.
  4. Miško Hevery. Flaw: Brittle Global State & Singletons. The Testability Explorer Blog. Архів оригіналу за 24 травня 2022. Процитовано 10 травня 2022.
  5. Michael C. Feathers (2005). The Case of the Irritating Global Dependency. Working Effectively with Legacy Code. Prentice Hall. ISBN 0-13-117705-2.
  6. Button, Brian (25 травня 2004). Why Singletons are Evil. Being Scott Densmore. Microsoft. Архів оригіналу за 15 липня 2021. Процитовано 28 серпня 2021.
  7. Klaus Iglberger (15 травня 2016). Thread-Safe Initialization of Data. Modernes CPP.
  8. Peter Muldoon (20 вересня 2020). Retiring the Singleton Pattern (PDF).
  9. а б Peter Haggar, IBM developerWorks: Double-checked locking and the Singleton pattern
  10. Singleton EJB
  11. а б Foundations of AOP for J2EE Development. Renaud Pawlak, Lionel Seinturier, and Jean-Philippe Retaillé. Apress 2005. ISBN 1-59059-507-6.
  12. Архівована копія. Архів оригіналу за 13 травня 2007. Процитовано 8 травня 2007.{{cite web}}: Обслуговування CS1: Сторінки з текстом «archived copy» як значення параметру title (посилання)
  13. Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Addison-Wesley, 1994. ISBN 0-201-63361-2

Див. також

Зовнішні посилання

Література

Алан Шаллоуей, Джеймс Р. Тротт. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М. : «Вильямс», 2002. — 288 с. — ISBN 0-201-71594-5.


Read other articles:

Artikel ini perlu diwikifikasi agar memenuhi standar kualitas Wikipedia. Anda dapat memberikan bantuan berupa penambahan pranala dalam, atau dengan merapikan tata letak dari artikel ini. Untuk keterangan lebih lanjut, klik [tampil] di bagian kanan. Mengganti markah HTML dengan markah wiki bila dimungkinkan. Tambahkan pranala wiki. Bila dirasa perlu, buatlah pautan ke artikel wiki lainnya dengan cara menambahkan [[ dan ]] pada kata yang bersangkutan (lihat WP:LINK untuk keterangan lebih lanjut...

 

American professional wrestler The BladeBlade in 2019Birth nameJesse Guilmette[1]Born (1980-06-03) June 3, 1980 (age 43)Buffalo, New York, U.S.Spouse(s) Allie ​(m. 2013)​[1]Professional wrestling careerRing name(s)The BladeBraxton Sutter[2]Pepper Parks Jesse GuilmetteBilled height6 ft 0 in (183 cm)[3]Billed weight220 lb (100 kg)[3]Billed fromBuffalo, New YorkErie, PennsylvaniaTrained byLes Thatc...

 

Drijber pada tahun 1987 Johannes Job Drijber (24 April 1924 – 22 Juni 2016)[1] adalah seorang hakim dan politikus Belanda dari VVD. Drijber adalah pembantu wali kota Leiden dan berturut-turut menjabat sebagai Wali kota Middelburg (1961-1969), Zwolle (1969-1980), dan Arnhem (1980-1989). Job Drijber menikah dengan Mary Halbertsma pada tahun 1951 dan memiliki 3 anak. Mary Halbertsma meninggal pada tahun 1991. Trivia Drijber pernah menjadi ketua Perserikatan Kotamadya Bela...

العلاقات العمانية الكورية الشمالية سلطنة عمان كوريا الشمالية   سلطنة عمان   كوريا الشمالية تعديل مصدري - تعديل   العلاقات العمانية الكورية الشمالية هي العلاقات الثنائية التي تجمع بين سلطنة عمان وكوريا الشمالية.[1][2][3][4][5] مقارنة بين البلدي...

 

كاتدرائية الأربعين شهيد أيقونة الدينونة الأخيرة في المحراب الشمالي داخل الكنيسةأيقونة الدينونة الأخيرة في المحراب الشمالي داخل الكنيسة معلومات أساسيّة الموقع حي الجديدة، حلب،  سوريا الانتماء الديني الأرمنية الأرثوذكسية تاريخ الرسامة 1429، جددت عام 1916[1] الطبيعة ك�...

 

Kazuhiko Chiba Informasi pribadiNama lengkap Kazuhiko ChibaTanggal lahir 21 Juni 1985 (umur 38)Tempat lahir Hokkaido, JepangPosisi bermain BekInformasi klubKlub saat ini Sanfrecce HiroshimaNomor 5Karier senior*Tahun Tim Tampil (Gol)2004-2005 AGOVV Apeldoorn 2005 Dordrecht 2005-2011 Albirex Niigata 2012- Sanfrecce Hiroshima Tim nasional2013 Jepang 1 (0) * Penampilan dan gol di klub senior hanya dihitung dari liga domestik Kazuhiko Chiba (lahir 21 Juni 1985) adalah pemain sepak bola asal ...

Ritratto di Petrus Valkenier Abraham van der Wenne, o Abraham Meindertzoon van der Wenne (Amsterdam, 26 febbraio 1656 o 1657 – Amsterdam, 1694 (tra il 1684 e il 1694)), è stato un incisore olandese del secolo d'oro. Biografia Allievo di Abraham Bloteling, operò inizialmente ad Amsterdam dal 1670 al 1672[1]. Nel 1672 si trasferì a Londra, dove rimase fino al 1678[1]. Ritornò infine nella sua città natale, dove operò tra il 1680 e il 1681[1]. Il 4 gennaio...

 

8th season in franchise history 2009 Houston Texans seasonOwnerBob McNairGeneral managerRick SmithHead coachGary KubiakOffensive coordinatorKyle ShanahanDefensive coordinatorFrank BushHome fieldReliant StadiumResultsRecord9–7Division place2nd AFC SouthPlayoff finishDid not qualifyPro Bowlers 5 QB Matt Schaub WR Andre Johnson ILB DeMeco Ryans OLB Mario Williams OLB Brian Cushing AP All-Pros 2 WR Andre Johnson (1st team) OLB Brian Cushing (2nd team) ← 2008 Texans seasons 2010&...

 

Mammalian protein found in humans Not to be confused with Angiotensin-converting enzyme 2 (ACE2). Angiotensin-converting enzyme monomer, Drosophila melanogasterIdentifiersEC no.3.4.15.1CAS no.9015-82-1 DatabasesIntEnzIntEnz viewBRENDABRENDA entryExPASyNiceZyme viewKEGGKEGG entryMetaCycmetabolic pathwayPRIAMprofilePDB structuresRCSB PDB PDBe PDBsumSearchPMCarticlesPubMedarticlesNCBIproteins ACEAvailable structuresPDBOrtholog search: PDBe RCSB List of PDB id codes1O86, 1O8A, 1UZE, 1UZF, 2C6F, 2...

1985 Invincible-class light aircraft carrier For other ships with the same name, see HMS Ark Royal. HMS Ark Royal alongside at Portsmouth in 2007 History United Kingdom NameArk Royal NamesakeThe 1587 flagship that defeated the Spanish Armada in 1588, Ark Royal OrderedDecember 1978 BuilderSwan Hunter, Tyne and Wear, United Kingdom Laid down14 December 1978 Launched2 June 1981 Sponsored byQueen Elizabeth The Queen Mother Commissioned1 November 1985 Decommissioned11 March 2011[2][3&#...

 

Ligne deVias à Lodève Carte de la ligne Vue du viaduc sur la Lergue, en avril 2024. Pays France Villes desservies Vias, Pézenas, Paulhan, Clermont-l'Hérault, Ceyras, Lodève Historique Mise en service 1863 Concessionnaires Midi (1854 – 1937)SNCF (1938 – 1997)RFF (1997 – 2014)SNCF (depuis 2015) Caractéristiques techniques Numéro officiel 732 000 Longueur 58,15 km Vitesse de référence 30 km/h[1] Écartement standard (1,435 m)...

 

نادي إكسلسيور تأسس عام 23 يوليو 1902  البلد هولندا  الدوري الدوري الهولندي الممتاز  المدرب مارينوس ديخوزن (29 يناير 2020–)[1]  الموقع الرسمي الموقع الرسمي  تعديل مصدري - تعديل   نادي إكسلسيور هو نادي كرة قدم هولندي تأسس عام 1902، ملعب الفريق هو ملعب فودشتاين وهو أ�...

American political commentator (born 1970) Michelle MalkinMalkin in 2016BornMichelle Maglalang (1970-10-20) October 20, 1970 (age 53)Philadelphia, Pennsylvania, U.S.EducationOberlin College (BA)Occupation(s)Political commentator, author, blogger, columnistPolitical partyRepublicanSpouse Jesse Malkin ​(m. 1993)​Children2 Michelle Malkin (/ˈmɔːlkɪn/; née Maglalang; born October 20, 1970)[1] is an American conservative political commentator. She was...

 

Standards organisation for Bluetooth technologies This article relies excessively on references to primary sources. Please improve this article by adding secondary or tertiary sources. Find sources: Bluetooth Special Interest Group – news · newspapers · books · scholar · JSTOR (April 2011) (Learn how and when to remove this message) Bluetooth Special Interest GroupThe Bluetooth SIG headquarters in Kirkland, WashingtonAbbreviationSIGFormationSeptember&#...

 

1990 single by Age of LoveThe Age of LoveSingle by Age of LoveReleasedMarch 1990 (Belgium)Recorded1990GenreTrance[1]techno[2]LabelDiKi RecordsSongwriter(s)Giuseppe Chierchia, Bruno SanchioniProducer(s)Bruno Sanchioni, Roger Samyn The Age of Love is a 1990 self-titled track by Italian-Belgian duo Age of Love. It is notable as an early popular example of trance music.[3] Released as a single in 1990 on the Belgian label DiKi Records,[4] it was written by Bruno Sa...

1982 film An Unsuitable Job for a WomanTrade advertisementDirected byChris PetitScreenplay byElizabeth McKayChris PetitBrian ScobieBased onAn Unsuitable Job for a Womanby P. D. JamesProduced byPeter McKayMichael RelphStarring Billie Whitelaw Paul Freeman Pippa Guard CinematographyMartin SchäferEdited byMick AudsleyProductioncompaniesGoldcrest FilmsNational Film Finance CorporationDistributed byGoldcrest FilmsRelease dates 16 February 1982 (1982-02-16) (Berlinale) 21 M...

 

هذه المقالة بحاجة لصندوق معلومات. فضلًا ساعد في تحسين هذه المقالة بإضافة صندوق معلومات مخصص إليها. هذه المقالة يتيمة إذ تصل إليها مقالات أخرى قليلة جدًا. فضلًا، ساعد بإضافة وصلة إليها في مقالات متعلقة بها. (أكتوبر 2018) سحلية صخور أرمنية الحياة البرية في أرمينيا تشملالخنازير ...

 

Northern realm of Powys Principality of Powys FadogTywysogaeth Powys Fadog1160–1277 Banner of Powys Fadog, known as the Black Lion of Powys Coat of Arms of Powys Fadog Powys as divided in 1190.CapitalDinas Brân and GlyndyfrdwyCommon languagesWelshGovernmentMonarchy• 1160–1191 Gruffydd Maelor I• 1191–1236 Madog ap Gruffydd Maelor• 1236–1269 Gruffydd II• 1269–1277 Madog II Historical eraMiddle Ages• Established 1160• Conquered and disman...

This page is an archive of past discussions. Do not edit the contents of this page. If you wish to start a new discussion or revive an old one, please do so on the current talk page. Japan Project‑class Japan portalThis page is within the scope of WikiProject Japan, a collaborative effort to improve the coverage of Japan-related articles on Wikipedia. If you would like to participate, please visit the project page, where you can join the project, participate in relevant discussions, and see...

 

1781 battle of the American Revolutionary War For other military actions at Pensacola, see Battle of Pensacola. Siege of PensacolaPart of the Gulf Coast Campaign of theAmerican Revolutionary War Spanish Troops at Pensacola, Florida by H. Charles McBarron shows a grenadier officer of the Louisiana regiment urging his troops to the assault at Pensacola.DateMarch 9 – May 10, 1781LocationPensacola, West Florida (present-day Florida)30°20′52″N 87°17′50″W / 30.34778°N 8...