Loner (suunnittelukuvio)

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 15.11.2020 tarkistetusta versiosta . vahvistus vaatii 101 muokkausta .
yksinäinen
Singleton
Tyyppi tuottaa
Plussat järjestää API:n; lataa implisiittisesti oikeat moduulit oikeassa järjestyksessä; jättää tilaa toiselle samanlaiselle esineelle
Miinukset monimutkaistaa testausta, monisäikeistä ja latenssiseurantaa; singletonin ei pitäisi implisiittisesti riippua toisistaan
Kuvattu suunnittelukuvioissa Joo

Singleton on generatiivinen suunnittelumalli  , joka takaa, että yksisäikeisessä sovelluksessa on yksi tietyn luokan esiintymä, ja tarjoaa maailmanlaajuisen yhteyspisteen tälle ilmentymälle.

Tarkoitus

Luokassa on vain yksi ilmentymä, ja se tarjoaa sille maailmanlaajuisen tukiaseman . Kun yrität luoda tämän objektin , se luodaan vain, jos sitä ei vielä ole olemassa, muuten palautetaan viittaus jo olemassa olevaan ilmentymään eikä uutta muistin varausta tapahdu. On oleellista, että on mahdollista käyttää luokan esiintymää , koska monissa tapauksissa laajempi toiminnallisuus tulee saataville. Esimerkiksi kuvattuihin luokkakomponentteihin pääsee käsiksi rajapinnan kautta , jos kieli tukee tällaista mahdollisuutta.

Joskus tarvitaan globaalia "yksinäistä" objektia - eli objektia ( ), ei toimintosarjaa, jota ei ole liitetty mihinkään objektiin ( ):log().put("Test");logPut("Test");

Tällaisia ​​objekteja voidaan luoda myös ohjelman alustuksen aikana. Tämä voi johtaa seuraaviin vaikeuksiin:

Plussat

Miinukset

Sovellus

Käyttöesimerkkejä

Toteutusesimerkkejä

Java 1.6

Java 1.6 -esimerkki: ei sisäisiä luokkia (laiska synkronoimaton toteutus) public class Singleton { yksityinen staattinen Singleton- instanssi ; yksityinen Singleton () {}; public static Singleton getInstance () { if ( instanssi == null ) { ilmentymä = new Singleton (); } palauttaa ilmentymä ; } }

Java

Java-esimerkki: Synchronized Accessor

Tämä vaihtoehto estää getInstance()-menetelmän riippumatta siitä, olemmeko luoneet yksittäisen esiintymän vai emme. Tämä hidastaa ohjelmaa, jos sinun täytyy saada Singleton-objekti eri säikeistä usein.

public class Singleton { yksityinen staattinen Singleton- instanssi ; yksityinen Singleton () {}; julkinen staattinen synkronoitu Singleton getInstance () { if ( instanssi == null ) { ilmentymä = new Singleton (); } palauttaa ilmentymä ; } }

Java

Java-esimerkki: ei laiska alustus, staattinen alustus public class Singleton { yksityinen staattinen Singleton- instanssi ; staattinen { esiintymä = uusi yksittäinen (); // Poikkeuskäsittely on mahdollista tässä lohkossa } yksityinen sinkku () {} public static Singleton getInstance () { return instanssi ; } }

Java 1.5

Java 1.5 -esimerkki: Initialization on Demand Holder julkinen luokka Singleton { yksityinen sinkku () {} yksityinen staattinen luokka SingletonHolder { julkinen staattinen lopullinen Singleton- instanssi = new Singleton (); } public static Singleton getInstance () { return SingletonHolder . esimerkki ; } }

Java 1.5

Java 1.5 esimerkki: Enum singleton public enum SingletonEnum { INSTANCE ; public void someMethod () { *** } public void otherMethod () { *** } }

Python

Julkaisusta PEP 0318 Arkistoitu 3. kesäkuuta 2020 Wayback Machinessa :

Python- esimerkki sisustajilla def singleton ( cls ): ilmentymät = {} def getinstance (): jos cls ei ilmentymissä : esiintymät [ cls ] = cls ( ) palauttaa ilmentymät [ cls ] palauttaa getinstance @singleton class MyClass : ...

Python

Julkaisusta PEP 0318 Arkistoitu 3. kesäkuuta 2020 Wayback Machinessa :

Python - esimerkki MetaClassesissa luokka MetaSingleton ( tyyppi ): _instances = {} def __call__ ( cls , * args , ** kwargs ): jos cls ei ole cls : ssä . _instances : cls . _instances [ cls ] = super ( MetaSingleton , cls ) . __call__ ( * args , ** kwargs ) palauttaa cls . _instances [ cls ] luokka MyClass ( metaclass = MetaSingleton ): ...

C++

Seuraava on yksi mahdollinen Singleton-mallin toteutus C++ :ssa (tunnetaan nimellä Myers singleton ), jossa singleton on staattinen paikallinen objekti. Tärkeää on, että luokan rakentaja on ilmoitettu muodossa private, mikä estää luokkaa ilmentämästä sen toteutuksen ulkopuolella. Lisäksi kopioinnin rakentaja ja toimeksiantooperaattori julistetaan yksityisiksi. Jälkimmäiset tulee ilmoittaa, mutta ei määritellä, koska tämä mahdollistaa helposti havaittavan linkitysvirheen, jos niitä kutsutaan vahingossa koodista. Huomaa myös, että yllä oleva esimerkki ei ole säikeille turvallinen C++03:ssa. Jos haluat työskennellä useista säikeistä koostuvan luokan kanssa, sinun on suojattava muuttuja theSingleInstancesamanaikaiselta käytöltä, esimerkiksi käyttämällä mutexia tai kriittistä osaa . Kuitenkin C++11 :ssä Myers singleton on lankaturvallinen ja lukitsematon.

Esimerkki C++:ssa luokka OnlyOne { julkinen : staattinen OnlyOne & Instance () { staattinen OnlyOne theSingleInstance ; palauttaa SingleInstance ; } yksityinen : OnlyOne (){} OnlyOne ( const OnlyOne & root ) = poista ; OnlyOne & operator = ( const OnlyOne & ) = delete ; };

Toinen esimerkki singletonin toteuttamisesta C ++:ssa, jossa on mahdollisuus periytyä rajapinnan luomiseksi, jonka kehys on itse asiassa singleton. Yksittäisen kohteen käyttöikää ohjataan kätevästi referenssilaskentamekanismin avulla .

Esimerkki C++:ssa luokan Singleton { suojattu : staattinen Singleton * _self ; Singleton () {} virtuaalinen ~ Singleton () {} julkinen : staattinen Singleton * Instanssi () { jos ( ! _itse ) { _self = uusi sinkku (); } return _self ; } staattinen bool DeleteInstance () { jos ( _itse ) { delete_self ; _ _itse = 0 ; return true ; } return false ; } }; Singleton * Singleton :: _self = 0 ;

C#

Esimerkki C# :ssa

Yksinkertaisin tapa toteuttaa säikeen turvallinen ja laiska singleton vaatii kuitenkin .NET-version 4 tai uudemman.

julkinen sinetöity luokka Singleton { yksityinen staattinen vain luku Laiska < Yksittäinen > ilmentymäHolder = new Lazy < Singleton >(() => new Singleton ()); yksityinen Singleton () { ... } public static Singleton Instance { get { return instanceHolder . arvo ; } } }

Singletonin laiskaa alustusta varten C#:ssa on suositeltavaa käyttää tyyppikonstruktoreja (staattista konstruktoria). CLR kutsuu automaattisesti tyypin rakentajan, kun tyyppiä käytetään ensimmäisen kerran, säilyttäen samalla säikeen synkronoinnin turvallisuuden. Kääntäjä luo automaattisesti tyyppikonstruktorin ja kaikki tyypin kentät (staattiset kentät) alustetaan siihen. Tyyppikonstruktoria ei pidä asettaa eksplisiittisesti, koska tässä tapauksessa se kutsutaan välittömästi ennen tyypin kutsumista ja JIT-kääntäjä ei voi käyttää optimointia (esimerkiksi jos ensimmäinen kutsu Singletonille tapahtuu silmukassa) .

/// yleinen Singleton<T> (säikeen turvallinen käyttämällä yleistä luokkaa ja laiska alustus) /// <typeparam name="T">Singleton-luokka</typeparam> public class Singleton < T > jossa T : luokka { /// Suojattua konstruktoria tarvitaan estämään Singleton-luokan instantoiminen. /// Sitä kutsutaan perityn luokan yksityiseltä rakentajalta. suojattu singleton () { } /// Tehdasta käytetään laiskasti alustamaan luokkaesiintymä yksityinen sinetöity luokka SingletonCreator < S > missä S : class { //Reflectionin käyttämä luokan luomiseen ilman julkista rakentajaa yksityinen staattinen vain luku S - instanssi = ( S ) typeof ( S ). GetConstructor ( BindingFlags . Instance | BindingFlags . NonPublic , null , new Type [ 0 ], new ParameterModifier [ 0 ]). Kutsu ( null ); public static S CreatorInstance { get { return instance ; } } } public static T - instanssi { get { return SingletonCreator < T >. CreatorInstance ; } } } /// Singletonin julkisen luokan käyttö TestClass : Singleton < TestClass > { /// Kutsuu Singleton-luokan suojattua konstruktoria private TestClass () { } public string TestProc () { return "Hei maailma" ; } }

Voit myös käyttää tavallista laiska-alustamista, säiettä suojaavaa Singleton-toteutusta:

public class Singleton { /// Suojattua konstruktoria tarvitaan estämään Singleton-luokan suojatun Singletonin esiintymän luominen () { } yksityinen sinetöity luokka SingletonCreator { yksityinen staattinen vain luku Yksittäinen esiintymä = new Singleton (); public static Singleton Instance { get { return instance ; } } } public static Singleton Instance { get { return SingletonCreator . Esimerkki ; } } }

Jos julkisia staattisia menetelmiä tai ominaisuuksia (muita kuin Instance-ominaisuutta) ei tarvita, voidaan käyttää yksinkertaistettua versiota:

public class Singleton { yksityinen staattinen vain luku Yksittäinen esiintymä = new Singleton (); public static Singleton Instance { get { return instance ; } } /// Suojattua konstruktoria tarvitaan estämään Singleton-luokan suojatun Singletonin esiintymän luominen () { } }

Laiska alustusesimerkki

nimiavaruus Singleton { public class Singleton { yksityinen staattinen Singleton- instanssi ; public static Singleton Instance { get { return instance ?? ( esimerkki = uusi yksittäinen ()); } } suojattu singleton () { } } }

PHP 4

Esimerkki PHP4 :ssä <?php class Singleton { function Singleton ( $directCall = true ) { if ( $directCall ) { trigger_error ( "Ei voida käyttää rakentajaa Singleton-luokan luomiseen. Käytä staattista getInstance() -metodia" , E_USER_ERROR ); } //TODO: Lisää pääkonstruktorikoodi tähän } function & getInstance () { staattinen $instance ; if ( ! on_objekti ( $instanssi ) ) { $luokka = __LUOKKA__ ; $instanssi = uusi $luokka ( false ); } return $instance ; } } //käyttö $test = & Singleton :: getInstance (); ?>

PHP 5

Esimerkki PHP5 :ssä <?php class Singleton { yksityinen staattinen $instance ; // objektiinstanssi yksityinen funktio __construct (){ /* ... @return Singleton */ } // Suojaa luomiselta uuden yksityisen Singleton- funktion kautta __clone () { /* ... @return Singleton */ } // Suojaa luominen kloonauksen avulla yksityinen funktio __wakeup () { /* ... @return Singleton */ } // Suojaa luomiselta unserialize -toiminnolla julkisen staattisen funktion getInstance () { // Palauttaa luokan yksittäisen esiintymän. @return Singleton if ( tyhjä ( itse :: $instance ) ) { self :: $instance = new self (); } return self :: $instance ; } julkinen toiminto doAction () { } } /* Sovellus */ Singleton :: getInstance () -> doAction (); // ?>

PHP 5.4

Esimerkki PHP5.4:ssä <?php ominaisuus Singleton { yksityinen staattinen $instanssi = null ; yksityinen funktio __construct () { /* ... @return Singleton */ } // Suojaa luomiselta uuden Singleton - yksityisen funktion kautta __clone () { /* ... @return Singleton */ } // Suojaa luomiselta kloonilla yksityinen function __wakeup () { /* ... @return Singleton */ } // Suojaa luomiselta poistamalla sarja julkinen staattinen funktio getInstance () { return self :: $instance === null ? self :: $instance = uusi staattinen () // Jos $instance on 'nolla', luo objekti uusi self() : self :: $instance ; // Muussa tapauksessa palauttaa olemassa olevan objektin } } /** * Luokka Foo * @method static Foo getInstance() */ class Foo { use Singleton ; yksityinen $bar = 0 ; public function incBar () { $this -> bar ++ ; } public function getBar () { return $this -> bar ; } } /* Hakemus */ $foo = foo :: getInstance (); $foo -> incBar (); var_dump ( $foo -> getBar ()); $foo = foo :: getInstance (); $foo -> incBar (); var_dump ( $foo -> getBar ()); ?>

Delphi

Delphi 2005 ja sitä uudemmat mallit soveltuvat seuraavaan esimerkkiin (ei lankaturvallinen):

Delphi esimerkki tyyppi TSingleton = luokka tiukka yksityinen luokka var Esim .: TSingleton ; julkinen luokkafunktio UusiInstanssi : TObject ; _ ohittaa ; loppu ; luokkafunktio TSingleton . _ Uusi ilmentymä : TObject ; aloita jos ei ole Assigned ( Instanssi ) then Instance := TSingleton ( peritty uusi ilmentymä ) ; Tulos := Instanssi ; loppu ;

Aiemmissa versioissa sinun tulee siirtää luokkakoodi erilliseen moduuliin ja Instancekorvata ilmoitus globaalin muuttujan ilmoituksella sen osiossa (ei ollut osioita implementationennen Delphi 7 :ää ). class varstrict private

Dart

Dart esimerkki

Perustuu Dart -dokumentaation tehdasrakentajaan

class Singleton { staattinen lopullinen Singleton _singleton = Singleton . _sisäinen (); tehdas Singleton () { return _singleton ; } singleton . _sisäinen (); }

Io

Io esimerkki Singleton := Objektiklooni Singleton klooni : = Yksittäinen

Ruby

Esimerkki Rubyssa luokka Singleton def self . uusi @instance ||= super end end

Vakiokirjasto (Ruby 1.8 ja uudempi) sisältää Singleton-moduulin, joka tekee singletonien luomisesta entistä helpompaa:

vaatia 'singleton' luokka Foo sisältää Singleton end a = Foo . esiintymä # Foo.new ei ole saatavilla, saadaksesi viittauksen Foo-luokan (yksittäiseen) # esiintymään, käytä Foo#instance-metodia

Common Lisp

Esimerkki julkaisussa Common Lisp ( defclass singleton-class () ;; metaluokka, joka toteuttaa singleton-mekanismin (( esimerkki :initform nil ))) ( defmethod validate- superclass (( class singleton-class ) ( superclass standard-class )) t ) ) ;;Salli singleton luokkien periä normaaleista luokista ( defmethod validate- superclass (( class singleton-class ) ( superclass singleton-class )) t ) ;;Salli singleton-luokkien periä muista singleton-luokista ( defmethod validate- superclass (( luokka standardi-luokka ) ( superclass singleton-class )) nolla ) ;;Estä tavallisia luokkia perimästä singletonista ( defmethod make-instanssi (( luokka singleton-class ) &key ) ( with-slots ( instanssi ) class ( tai ilmentymä ( setf ilmentymä ( call-next-method ))))) ( defclass my-singleton-class () () ( :metaclass singleton-class ))

VB.NET

Esimerkki: VB.NET Moduuli ohjelma Sub Main () Dim T1 As Singleton = Singleton . getInstance T1 . arvo = 1000 Dim T2 As Singleton = Singleton . getInstance- konsoli . WriteLine ( T2 . Arvo ) konsoli . Lue () End Sub Lopeta moduuli Public Class Singleton Julkinen arvo kokonaislukuna _ Älä salli suojattua alikonstruktoria Uusi () End Sub Yksityinen Ei perinnöllinen luokka SingletonCreator Yksityinen Jaettu Vain luku m_instance Uutena singletonina () Julkinen jaettu vain luku -omaisuuden ilmentymä ( ) Singleton Get Return m_instance End Get End -omaisuuden loppuluokka Julkinen jaettu vain luku -ominaisuus getInstance () Singletonina Get Return SingletonCreator . Ilmentymän loppu Hanki loppuominaisuus _ loppuluokka _

Perl

Perl esimerkki käytä v5.10 ; _ käytä tiukkaa ; paketti Singleton ; sub new { # Staattisen muuttujan $instance # ilmoittaminen ja sen palauttaminen menetelmän suorittamisen seurauksena new state $instance = bless {}; } pääpaketti ; _ minun $a = Singleton -> uusi ; minun $b = Singleton -> uusi ; sano "$a $b" ; # Viittaukset $a ja $b osoittavat samaan objektiin

Perl

Perl- esimerkki muuttumattomalla objektilla #!/usr/bin/perl -w käytä ominaisuutta "sano" ; käytä tiukkaa ; käytä varoituksia ; paketti Singleton { minun $instance ; # luokan esiintymä (staattinen kenttä) # -- ** rakentaja ** -- sub new { minun $luokka = shift ; ellei ( $instance ) { # tarkista onko jo olemassa esiintymä luokasta $instance = { # jos ei, luo uusi ja kirjoita tervehtivän henkilön nimi nimi => shift , }; siunaa $instance , $class ; } return $instance ; # palauttaa luokkamme ainoan esiintymän } # -- ** hei ** -- sub hei { minun ( $itse ) = ( vaihto ); sano "Hei, $self->{name}" ; # tervehditään tämän kohteen omistajaa } } minun $a = Singleton -> uusi ( 'Alex' ); # luo ilmentymä luokasta nimeltä Alex my $b = Singleton -> new ( 'Barney' ); # ... yritän nyt luoda toista ilmentymää Barneylle $a -> hello (); # Hei, Alex # kyllä, hei Alex $b -> hei (); # Hei, Alex # oho, Barney, anteeksi, mikä väärinkäsitys...

ActionScript 3

ActionScript- esimerkki

Yksityistunnin vaihtoehto:

paketti { public class Singleton { yksityinen staattinen var _instance : Singleton ; Julkinen toiminto Singleton ( privateClass : PrivateClass ) { } julkinen staattinen funktio getInstance () : Singleton { if ( ! _instance ) _instance = new Singleton ( uusi yksityinen luokka ()); return _instance ; } } } // Koska luokka on ilmoitettu samassa tiedostossa // paketin ulkopuolella, vain Singleton-luokka voi käyttää sitä. class PrivateClass { julkinen toiminto PrivateClass () { } }

Poikkeusvaihtoehdon heittäminen:

paketti { julkinen luokka yksittäinen { julkinen staattinen vakioinstanssi : Singleton = new Singleton ( ); public function Singleton () { // Boolen(Singleton) on epätosi, jos luokka // instantioidaan ennen kuin staattinen konstruktori suoritetaan if ( Singleton ) heittää new Error ( "Luokka on singleton." ); } } }

Vaihtoehto pääsymuuttujalla:

paketti { julkinen luokka MySingleton { yksityinen staattinen var _instance : MySingleton ; // Pääsy muuttujaan private static var _isConstructing : Boolean ; public function MySingleton () { if ( ! _isConstructing ) throw new Error ( "Singleton, käytä MySingleton.instance" ); } julkinen staattinen funktio hanki ilmentymä () : MySingleton { if ( _instance == null ) { _isConstructing = true ; _instance = uusi MySingleton (); _isConstructing = false ; } return _instance ; } } }

Yksityisluokkavaihtoehdon edut:

  • Jos yrität käyttää konstruktoria suoraan, kääntäjä huomaa virheen heti. // Ei tämän menetelmän ainoa etu
  • Objekti luodaan pyynnöstä.

Yksityisluokkavaihtoehdon haittapuoli:

  • Voit korvata yksityisen luokan omallasi samalla nimellä.

Poikkeusvaihtoehdon edut:

  • Vähemmän koodia.

CoffeeScript

Esimerkki CoffeeScriptistä

Klassinen lähestymistapa (Coffeescript ≠ 1,5)

luokka Yksittäinen ilmentymä = määrittelemätön konstruktori : -> jos ilmentymä ? palauta ilmentymä muu ilmentymä = @ # Rakentajakoodi konsoli . väittää ( uusi Singleton on uusi Singleton );

Lähestymistapa perustuu mahdollisuuteen käyttää toimintoa sen rungosta (Coffeescript ≠ 1,5)

luokka Singleton init = -> # konstruktori yksityisenä luokan menetelmänä # Konstruktorikoodi # ... # Korvaa konstruktori pitäen tämä (@) init = => @ return @ # Todellinen rakentaja. Palvelee kutsua init # return on käytettävä, muuten se palauttaa tämän (@) konstruktorin : -> return init . soveltaa ( @ , argumentit ) konsoli . väittää ( uusi Singleton on uusi Singleton ) Huomaa: todellisen konstruktorin muuttaminen itsestään, ts. rakentaja : -> Singleton = => @ ei anna mitään, koska tuloksena olevassa JavaScript-koodissa konstruktori osoittaa paikalliseen Singleton-konstruktoriin, ei Singleton-luokkaan.

Jos kuitenkin käytät nimiavaruuksia, tämä vaihtoehto on mahdollinen:

ns = {} luokka ns . Yksittäinen konstruktori : -> # Rakennuskoodi ns.Singleton == > @ konsoli . Assert ( uusi ns . Singleton on uusi ns . Singleton )

JavaScript

JavaScript - esimerkki kapseloimalla

Menetelmä, joka perustuu muuttujien piilottamiseen sulkemisilla. Bonuksena - kyky ilmoittaa yksityisiä menetelmiä ja ominaisuuksia, jotka ovat sekä rakentajan että "luokka" -menetelmien käytettävissä.

const Singleton = ( funktio () { anna ilmentymä ; // Yksityiset menetelmät ja ominaisuudet // Konstruktorifunktio Singleton ( ) { if ( instanssi ) return instanssi ; esimerkki = tämä ; } // Public Methods Singleton . prototyyppi . testi = funktio () {}; paluu Singleton ; })(); konsoli . log ( new Singleton () === new Singleton ());

Ilman muuttujan piilottamista on olemassa yksinkertainen ratkaisu, joka perustuu siihen, että Singleton-funktio on objekti. Huono puoli on kyky muuttaa ilmentymän ominaisuutta luokan ulkopuolella:

function Singleton () { const instance = Singleton . esimerkki ; if ( instanssi ) return instanssi ; singleton . esimerkki = tämä ; } singleton . prototyyppi . testi = funktio () {}; konsoli . log ( new Singleton () === new Singleton ());

Lyhin vaihtoehto.

const Singleton = uusi ( funktio () { const- instanssi = tämä ; paluufunktio ( ) { paluuinstanssi ; } ; })(); konsoli . log ( new Singleton () === new Singleton ());

JS-luokan staattisten yksityisten kenttien käyttäminen:

class Singleton { static # onlyInstance = null ; rakentaja (){ if ( ! Yksittäinen . # vainInstanssi ){ Yksittäinen . # onlyInstance = tämä ; } else { return Singleton . # onlyInstance ; } } } konsoli . log ( new Singleton () === new Singleton ());

Objective-C

Esimerkki Objective-C :ssä

singleton.h

@interface Singleton  : NSObject { } + ( Singleton * ) sharedInstance ; @loppu

singleton.m

@implementationSingleton _ staattinen Singleton * _sharedInstance = nolla ; + ( Singleton * ) sharedInstance { @synchronized ( itse ) { if ( ! _sharedInstance ) { _sharedInstance = [[ Singleton alloc ] init ]; } } return _sharedInstance ; } @loppu

Tai (vain OS X 10.6+, iOS 4.0+):

@implementationSingleton _ + ( Singleton * ) sharedInstance { staattinen lähetys_once_t pred ; staattinen Singleton * SharedInstance = nolla ; dispatch_once ( & pred , ^ { sharedInstance = [[ self alloc ] init ]; }); palauttaa sharedInstance ; } @loppu

Swift

Nopea esimerkki class Singleton { staattinen anna jaettu = Singleton () yksityinen init () { } }

Scala, Kotlin

Esimerkki Scalassa ja Kotlinissa object Singleton {} // avainsana "objekti" luo luokan, joka toteuttaa "singleton" mallin oletuksena

Katso myös

Kirjallisuus

  • Alan Shalloway, James R. Trott Design Patterns. Uusi lähestymistapa olio-suuntautuneeseen suunnitteluun = Design Patterns Explained: A New Perspective on Object-Oriented Design. - M .: "Williams", 2002. - S. 288. - ISBN 0-201-71594-5 .
  • Eric Freeman, Elizabeth Freeman. Suunnittelukuviot = Head First Design Patterns. - Pietari. : Peter, 2011. - 656 s. - ISBN 978-5-459-00435-9 .

Linkit

Muistiinpanot