Objektiallas

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 5. huhtikuuta 2022 tarkistetusta versiosta . tarkastukset vaativat 4 muokkausta .
Objektiallas
objektipooli
Tyyppi tuottaa
Kuvattu suunnittelukuvioissa Ei

Objektivarasto  on luova suunnittelumalli , joukko alustettuja ja käyttövalmiita objekteja. Kun järjestelmä tarvitsee objektin, sitä ei luoda, vaan se otetaan poolista. Kun esinettä ei enää tarvita, sitä ei tuhota, vaan se palautetaan altaaseen.

Sovellus

Objektien yhdistämistä käytetään suorituskyvyn parantamiseen, kun objektin luominen työn alussa ja sen tuhoaminen lopussa on kallista. Suorituskyvyn paraneminen on erityisen havaittavissa, kun esineitä luodaan ja tuhotaan usein, mutta niitä on olemassa vain pieni määrä samanaikaisesti.

Objektivarasto on hyödyllinen, kun objekti omistaa muita resursseja kuin muistia, kuten verkkopistokkeita. Tai jos objektikokoelma vie huomattavan osan tietokoneen muistista ja syntyy paljon " roskaa ".

Ylivuoto

Jos poolissa ei ole yhtään vapaata objektia, yksi kolmesta strategiasta on mahdollinen:

  1. Altaan laajennus.
  2. Kieltäytyminen esineen luomisesta, hätäpysäytys.
  3. Jos kyseessä on moniajojärjestelmä , voit odottaa, kunnes jokin objekteista vapautetaan.

Esimerkkejä

  1. Tietoja avoimista tiedostoista DOSissa .
  2. Tietoa näkyvistä esineistä monissa tietokonepeleissä ( Doom-moottori on hyvä esimerkki ). Nämä tiedot koskevat vain yhtä kehystä; kun kehys on tulostettu, luettelo tyhjenee.
  3. Kaikkien kartan kohteiden tallentamiseen tarkoitettu tietokonepeli voi tavanomaisten muistinvarausmekanismien sijaan luoda sellaisen kokoisen taulukon , että sen tiedetään riittävän kaikille objekteille, ja säilyttää vapaat solut linkitetyn listan muodossa. . Tämä muotoilu parantaa nopeutta, vähentää muistin pirstoutumista ja vähentää roskankeräimen kuormitusta (jos sellainen on).

Ansoja

  1. Kun esine on palautettu, sen on palattava jatkokäyttöön sopivaan tilaan. Jos objektit ovat altaaseen palaamisen jälkeen väärässä tai määrittelemättömässä tilassa, tällaista rakennetta kutsutaan objektivarastoksi . 
  2. Esineiden uudelleenkäyttö voi myös johtaa tietovuotoon. Jos objekti sisältää salaisia ​​tietoja (esimerkiksi luottokortin numeron ), objektin julkaisun jälkeen nämä tiedot on kirjoitettava päälle.
  3. Monisäikeistä objektipoolia ei ole helppo kirjoittaa.
  4. 2020-luvulle roskakorjauskielillä muistinhallinta on hyvin optimoitu jatkuvaa allokointia varten. Joten jos objekti vie vain muistia, Java-käsikirjat eivät suosittele poolien käyttöä: tavallinen newvaatii vain kymmenen prosessoriohjetta. Ja roskankerääjät skannaavat usein objektiviittauksia, eivät niiden muistia - koska mitä enemmän "eläviä" objekteja muistissa on, sitä heikompi tällaisen kerääjän suorituskyky on.

Toteutusesimerkki

Python- esimerkki

Lähdekoodi Pythonissa #koodaus: utf-8 """ Kuvittele tilanne, jossa meillä on laiva, joka kestää useita laukauksia. Shot-objektin luominen on kallista. Siksi Shot-perheen esineitä luodaan kerran. Ja eliniän jälkeen esine jää muisti. """ luokka Shot ( objekti ): """Entiteetti, joka voi selviytyä useista osumista""" def __init__ ( self , lifetime = 5 ): itse . elinikä = elinikä def update ( itse ): itse . käyttöikä = 1 palautus itse . käyttöikä > 0 class ObjectPool : """Objektivarasto""" def __init__ ( self , ** kwargs ): """Luodaan poolia""" itse . _clsname = kwargs [ 'luokan nimi' ] self . _args = kwargs . saada ( 'args' , []) itse . _num_objects = max ( kwargs [ 'num' ], 0 ) self . _pred = kwargs [ 'update_func' ] self . _max_objects = kwargs . get ( 'max' , itse . _num_objects ) # Luo objektit itse . _objs = [ soveltaa ( itse . _clsname , self . _args ) x alueella ( itse . _num_objects ) ] self . _ _end = len ( itse . _objs ) def _extend_list ( self , args ): """Lisää yksi paikka pooliin""" self . _objs . append ( soveltaa ( itse . _clsname , args )) itse . _objektien_määrä += 1 def add ( self , * args ): """Lisää yksi objekti pooliin""" newend = self . _end + 1 # Jos maksimi saavutetaan, katkaise puhelin, jos newend > self . _max_objects : return Ei mitään # Jos kaikki paikat on varattu, lisää yksi paikka lisää if newend > len ( self . _objs ): self . _extend_list ( args ) else : self . _objs [ itse . _end ] . nollaa ( * args ) itse . _end += 1 palauttaa itsensä . _end - 1 def update ( self , * args ): """Päivitä kaikki poolin objektit""" itse . _end = osio ( self . _pred , self . _objs , 0 , itse . _end , args ) palauttaa itsensä . _end def update_object ( x ): """Päivitä objekti""" palauttaa x . päivitys () def- osio ( pred , seq , ensimmäinen , viimeinen , * args ): """Objektilajittelutoiminto""" if first > last : return 0 i :lle alueella ( ensimmäinen , viimeinen ) : jos ei pred ( seq [ i ]): break else : palauta viimeinen j :lle alueella ( i + 1 , viimeinen ) : jos pred ( sek [ j ]): sek [ i ], sek [ j ] = sek [ j ], sek [ i ] i += 1 paluu i # Itse asiassa pool shots = ObjectPool ( luokan nimi = Shot , update_func = update_object , num = 5 ) käyttäminen laukausten aikana . päivitys (): pass tulosta "Valmis!"

C++ esimerkki

Lähdeteksti C++:ssa #sisällytä <vektori> luokan objekti { // ... }; luokan ObjectPool { yksityinen : struct PoolRecord { objekti * ilmentymä ; bool in_use ; }; std :: vektori < PoolRecord > m_pool ; julkinen : Objekti * createNewObject () { for ( koko_t i = 0 ; i < m_pool . koko (); ++ i ) { if ( ! m_pool [ i ]. in_use ) { m_pool [ i ]. in_use = tosi ; // siirtää objekti käytettyjen listaan ​​return m_pool [ i ]. esimerkki ; } } // jos emme löytäneet vapaata objektia, laajenna PoolRecord- tietue ; ennätys . esiintymä = uusi objekti ; ennätys . in_use = tosi ; m_pool . push_back ( ennätys ); paluu ennätys . esimerkki ; } void deleteObject ( Object * objekti ) { // todellisuudessa emme poista, vaan merkitsemme vain, että objekti on vapaa ( koko_t i = 0 ; i < m_pool . size ( ); ++ i ) { if ( m_pool [ i ]. ilmentymä == objekti ) { m_pool [ i ]. in_use = false ; tauko ; } } } virtuaalinen ~ ObjectPool () { // nyt "todella" poistamme objektit kohteelle ( koko_t i = 0 ; i < m_pool . size (); ++ i ) poista m_pool [ i ]. esimerkki ; } }; int main () { Objektiallas ; _ for ( koko_t i = 0 ; i < 1000 ; ++ i ) { Objekti * objekti = pooli . CreateNewObject (); // ... allas . deleteObject ( objekti ); } paluu 0 ; }

Mallit ja lankasuojat on poistettu esimerkistä yksinkertaisuuden vuoksi . Jos haluat käyttää poolia useissa säikeissä, sinun tulee suojata createNewObject- ja deleteObject-menetelmien runko jonkin sopivan synkronointiobjektin, kuten kriittisen osan tai mutexin , samanaikaiselta suorittamiselta .

Esimerkki C# :ssa

Lähdeteksti C# nimitila Digital_Patterns.Creational.Object_Pool.Soft { /// <summary> /// Käyttöliittymä "Object Pool" -mallin käyttämiseen <katso cref="Object_Pool"/> /// </summary> /// <typeparam name= " T"></typeparam> julkinen käyttöliittymä ICreation < T > { /// <summary> /// Palauttaa juuri luodun objektin /// </summary> /// <returns></returns> T Luo () ; } } Lähdeteksti C# käyttäen System ; käyttämällä System.Collections -ohjelmaa ; käyttäen System.Threading ; nimiavaruus Digital_Patterns.Creational.Object_Pool.Soft { /// <summary> /// Objektivarannon toteuttaminen pehmeillä viittauksilla /// </summary> /// <typeparam name="T"></typeparam> julkinen luokka ObjectPool < T > missä T : luokka { /// <summary> /// Synkronointiobjekti /// </summary> yksityinen semafori semafori ; /// <summary> /// Kokoelma sisältää hallittuja objekteja /// </summary> yksityinen ArrayList pool ; /// <summary> /// Viittaus objektiin, jolle on delegoitu vastuu /// poolin objektien luomisesta /// </summary> yksityinen ICreation < T > creator ; /// <summary> /// Olemassa olevien objektien määrä /// </summary> private Int32 instanceCount ; /// <summary> /// Poolin hallitsemien objektien enimmäismäärä /// </summary> yksityinen Int32 maxInstances ; /// <summary> /// Objektivarannon luominen /// </summary> /// <param name="creator">Objekti, jolle pooli siirtää vastuun /// hallinnoimiensa objektien luomisesta< /param> public ObjectPool ( ICreation < T > luoja ) : this ( luoja , Int32 . MaxValue ) { } /// <summary> /// Objektivarannon luominen /// </summary> /// <param name="creator">Objekti, jolle pooli siirtää vastuun /// hallinnoimiensa objektien luomisesta< /param> / // <param name="maxInstances">Luokkien enimmäismäärä /// jonka pooli sallii olla olemassa samanaikaisesti /// </param> public ObjectPool ( ICreation < T > creator , Int32 maxInstances ) { this . luoja = luoja ; tämä . instanssimäärä = 0 ; tämä . maxInstances = maxInstances ; tämä . pool = uusi ArrayList (); tämä . semafori = uusi Semafori ( 0 , tämä . maxInstances ); } /// <yhteenveto> /// Palauttaa uudelleenkäyttöä odottavien objektien lukumäärän poolissa . Todellinen luku /// voi olla pienempi kuin tämä arvo, koska /// palautettu arvo on poolissa olevien pehmeiden viittausten määrä. /// </summary> public Int32 Size { get { lock ( pool ) { return pool . laskea ; } } } /// <summary> /// Palauttaa tällä hetkellä olemassa olevien poolattujen objektien määrän /// /// </summary> public Int32 InstanceCount { get { return instanceCount ; } } /// <yhteenveto> /// Hae tai aseta enimmäismäärä /// hallittuja objekteja, jotka pooli sallii olla olemassa samanaikaisesti. /// </summary> public Int32 MaxInstances { get { return maxInstances ; } set { maxInstances = arvo ; } } /// <yhteenveto> /// Palauttaa objektin poolista. Tyhjällä poolilla /// objekti luodaan, jos poolin hallitsemien objektien /// määrä ei ole suurempi tai yhtä suuri kuin <katso cref="ObjectPool{T}" palauttama arvo ///. MaxInstances"/> -menetelmä. Jos poolin hallitsemien objektien määrä /// ylittää tämän arvon, tämä menetelmä palauttaa null /// </summary> /// <returns></returns> public T GetObject () { lock ( pool ) { T thisObject = PoistaObject ( ); if ( thisObject != null ) return thisObject ; if ( InstanceCount < MaxInstances ) return CreateObject (); palauttaa null ; } } /// <yhteenveto> /// Palauttaa objektin poolista. Tyhjällä poolilla /// objekti luodaan, jos poolin hallitsemien objektien /// määrä ei ole suurempi tai yhtä suuri kuin <katso cref="ObjectPool{T}" palauttama arvo ///. MaxInstances"/> -menetelmä. Jos poolin hallitsemien objektien /// määrä ylittää tämän arvon, tämä menetelmä odottaa kunnes /// kunnes jokin objekti tulee saataville /// uudelleenkäyttöön. /// </summary> /// <returns></returns> public T WaitForObject () { lock ( pool ) { T thisObject = RemoveObject (); if ( thisObject != null ) return thisObject ; if ( InstanceCount < MaxInstances ) return CreateObject (); } semafori . odottaja (); return WaitForObject (); } /// <summary> /// Poistaa objektin poolikokoelmasta ja palauttaa sen /// </summary> /// <returns></returns> yksityinen T PoistaObject () { while ( pool . Count > 0 ) { var refThis = ( WeakReference ) pool [ pool . Count - 1 ]; allas . RemoveAt ( pool . Count - 1 ); var thisObject = ( T ) refThis . Kohde ; if ( thisObject != null ) return thisObject ; instanceCount --; } return null ; } /// <summary> /// Luo tämän poolin hallinnoima objekti /// </summary> /// <returns></returns> yksityinen T CreateObject () { T newObject = luoja . luo (); instanceCount ++; return newObject ; } /// <summary> /// Vapauttaa objektin ja sijoittaa sen pooliin /// uudelleenkäyttöä varten /// </summary> /// <param name="obj"></param> /// <poikkeus cref ="NullReferenceException"></exception> public void Release ( T obj ) { if ( obj == null ) throw new NullReferenceException (); lukko ( pool ) { var refThis = new WeakReference ( obj ); allas . Lisää ( refThis ); semafori . vapauttaa (); } } } } Lähdeteksti C# nimiavaruus Digital_Patterns.Creational.Object_Pool.Soft { julkinen luokka Uudelleenkäytettävä { julkinen objekti [] Objs { get ; suojattu sarja ; } public Uudelleenkäytettävä ( params Object [ ] objs ) { this . Objs = objs ; } } public class Luoja : ICreation < Uudelleen käytettävä > { yksityinen staattinen Int32 iD = 0 ; public Uudelleen käytettävä Luo () { ++ iD ; palauta uusi Uudelleen käytettävä ( iD ); } } public class ReusablePool : ObjectPool < Uudelleenkäytettävä > { public ReusablePool () : base ( new Creator (), 2 ) { } } } Lähdeteksti C# käyttäen System ; käyttäen System.Threading ; käyttäen Digital_Patterns.Creational.Object_Pool.Soft ; nimiavaruus Digital_Patterns { luokka Ohjelma { static void Main ( merkkijono [ ] args ) { Konsoli . WriteLine ( System . Reflection . MethodInfo . GetCurrentMethod ( . Nimi ); var reusablePool = uusi ReusablePool (); var thrd1 = uusi säie ( Suorita ); var thrd2 = uusi säie ( Suorita ); var thisObject1 = reusablePool . GetObject (); var thisObject2 = reusablePool . GetObject (); kolmas 1 . Käynnistä ( reusablePool ); kolmas 2 . Käynnistä ( reusablePool ); ViewObject ( thisObject1 ); ViewObject ( thisObject2 ); lanka . Sleep ( 2000 ); uudelleenkäytettävä allas . Vapauta ( thisObject1 ); lanka . Sleep ( 2000 ); uudelleenkäytettävä allas . Vapauta ( thisObject2 ); konsoli . ReadKey (); } yksityinen static void Suorita ( Objektiobjekti ) { Konsoli . _ WriteLine ( "\t" + System . Reflection . MethodInfo . GetCurrentMethod (). Nimi ); var reusablePool = ( ReusablePool ) obj ; konsoli . WriteLine ( "\tstart odottaa" ); var thisObject1 = reusablePool . WaitForObject (); ViewObject ( thisObject1 ); konsoli . WriteLine ( "\tend wait" ); uudelleenkäytettävä allas . Vapauta ( thisObject1 ); } yksityinen static void ViewObject ( Uudelleen käytettävä thisObject ) { foreach ( var obj in thisObject . Objs ) { Console . Kirjoita ( obj . ToString () + @" " ); } Konsoli . writeLine (); } } }

VB.NET esimerkki

Lähdeteksti VB.NET-kielellä Nimiavaruus Digital_Patterns.Creational.Object_Pool.Soft ' Käyttöliittymä "Object Pool" -mallin käyttöön <katso cref="Object_Pool"/> Julkinen käyttöliittymä ICreation ( Of T ) ' Palauttaa juuri luodun objektin Function Create () As T End Interface lopeta nimiavaruus Lähdeteksti VB.NET-kielellä Nimiavaruus Digital_Patterns.Creational.Object_Pool.Soft "Objektivarannon toteutus pehmeillä viittauksilla Public Class ObjectPool ( Of T As Class ) ' Synkronoi objekti Yksityinen semafori Semaforina Kokoelma sisältää hallittuja objekteja Yksityinen pooli ArrayList - muodossa Viittaus objektiin, jolle on delegoitu vastuu poolin Private Creator As ICreation ( Of T ) objektien luomisesta 'Tällä hetkellä olemassa olevien objektien lukumäärä Yksityinen m_instanceCount As Int32 Poolattujen objektien enimmäismäärä Yksityinen m_maxInstances As Int32 'Object Pool Creation ' -luoja on objekti, jolle pooli siirtää vastuun hallinnoimiensa objektien luomisesta Public Sub New ( ByVal creator As ICreation ( Of T )) Me . Uusi ( luoja , Int32 . MaxValue ) End Sub Kohdevarannon luonti -objekti, jolle pooli siirtää vastuun hallinnoimiensa objektien luomisesta . maxInstances - Luokan esiintymien enimmäismäärä, jonka pooli sallii olla olemassa samanaikaisesti Public Sub New ( ByVal luoja Kuten ICreation ( Of T ), ByVal maxInstances As Int32 ) me . luoja = luoja minä . m_instanceCount = 0 Me . m_maxInstances = maxInstances Me . pool = Uusi ArrayList () Minä . semafori = Uusi semafori ( 0 , minä . m_maxInstances ) End Sub 'Palauttaa uudelleenkäyttöä odottavien kohteiden määrän poolissa . Todellinen luku voi olla pienempi kuin tämä arvo, koska palautettu arvo on joukossa olevien pehmeiden viittausten määrä. Julkinen vain luku -omaisuuden koko ( ) Int32 :na Hanki SyncLock - varasto Return pool . Count End SyncLock End Hanki loppuominaisuus _ 'Palauttaa tällä hetkellä olemassa olevien poolattujen objektien määrän. Julkinen vain luku -ominaisuus InstanceCount () Kuten Int32 Get Return m_instanceCount End Get End Property "Hanki tai aseta poolin hallinnoimien "objektien enimmäismäärä , jonka pooli sallii olla olemassa kerrallaan. Julkisen omaisuuden enimmäisinstanssit () Int32 : na Hae palautus m_maxInstances End Get Set ( ByVal arvo Int32 : na ) m_maxInstances = arvo Loppujoukko Lopetusominaisuus 'Palauttaa kohteen altaalta. Tyhjä pooli luo objektin, jos poolin hallitsemien objektien määrä ei ole suurempi tai yhtä suuri kuin ObjectPool{T}.MaxInstances-metodin palauttama arvo. ' Jos poolattujen objektien määrä ylittää tämän arvon, tämä 'menetelmä palauttaa nollan Public Function GetObject () As T SyncLock pool Dim thisObject muodossa T = RemoveObject ( ) If thisObject IsNothing then Return thisObject End If If InstanceCount < MaxInstances Then Return CreateObject () End If Return Nothing End SyncLock lopetustoiminto _ ' Palauttaa kohteen altaalta. Tyhjä pooli luo "objektin, jos poolattujen objektien määrä " ei ole suurempi tai yhtä suuri kuin ObjectPool{T}-menetelmän palauttama arvo. MaxInstances-metodi ' Jos poolattujen objektien määrä ylittää tämän arvon, ' tämä menetelmä odottaa kunnes esinettä ei anneta uudelleen käytettäväksi. Julkinen toiminto WaitForObject () As T SyncLock pool Himmeä tämä Object muodossa T = PoistaObject ( ) Jos tämä objekti ei ole mitään , palauta tämäObjekti Lopeta jos If InstanceCount < MaxInstances Then Return CreateObject () End If End SyncLock semafori . WaitOne () Return WaitForObject () Lopeta funktio ' Poistaa objektin poolikokoelmasta ja palauttaa sen Yksityinen toiminto RemoveObject () As T While pool . Count > 0 Dim refThis = DirectCast ( pool ( pool . Count - 1 ), WeakReference ) pool . RemoveAt ( pool . Count - 1 ) Himmeä tämäObject = DirectCast ( refThis . Target , T ) Jos tämä objekti ei ole mitään , sitten palauta tämäObject End If m_instanceCount - = 1 End While Return Nothing Lopetustoiminto ' Luo tämän poolin hallitsema objekti Yksityinen toiminto CreateObject ( ) As T Dim newObject As T = luoja . Luo () m_instanceCount += 1 Palauta newObject End Function ' Vapauttaa objektin ja sijoittaa sen pooliin uudelleenkäyttöä varten Julkinen alijulkaisu ( ByVal obj As T ) Jos obj ei ole mitään , sitten Heitä uusi NullReferenceException () End If SyncLock pool Dim refThis = Uusi WeakReference ( obj ) pool . Lisää ( refThis ) semafori . Vapauta () End SyncLock End Sub End Class End Namespace Lähdeteksti VB.NET-kielellä Nimiavaruus Digital_Patterns.Creational.Object_Pool.Soft '### Luokka Uudelleenkäytettävä #### Julkinen luokka Uudelleenkäytettävä Yksityinen m_Objs Objektina ( ) Julkinen Sub Uusi ( ByVal ParamArray objs Objektina () ) Minä . Objs = objs End Sub Julkinen omaisuus Objs () Objektina ( ) Hae Palautus m_Objs End Get Suojattu joukko ( ByVal arvo Objektina ( ) ) m_Objs = arvo Lopetusjoukko End Property End Class "### Class Creator #### Public Class Creator toteuttaa ICreationin ( uudelleenkäytettävän ) Yksityinen jaettu tunnus Int32 = 0 _ Julkinen toiminto Luo ( ) uudelleenkäytettävinä toteuttaa ICreationin ( uudelleenkäytettävien ) . Luo iD += 1 Palauta uusi uudelleenkäytettävä ( iD ) End Function End Class '### ReusablePool-luokka #### Julkinen luokka ReusablePool perii ObjectPool ( uudelleenkäytettävän ) Julkinen Sub Uusi () MyBase . Uusi ( Uusi luoja (), 2 ) End Sub End Class End Namespace Lähdeteksti VB.NET-kielellä Tuo System.Threading Imports Digital_Patterns.Creational.Object_Pool.Soft Namespace Digital_Patterns Class Program Jaettu Sub- pääkonsoli ( ) . WriteLine ( System . Reflection . MethodInfo . GetCurrentMethod ( . Nimi ) Dim reusablePool = Uusi Uudelleenkäytettävä Pool ( ) Dim thrd1 = Uusi säie ( AddressOf Run ) Dim thrd2 = Uusi säie ( AddressOf Run ) Dim thisObject1 = reusablePool . GetObject () Dim thisObject2 = reusablePool . GetObject () kolmas 1 . Käynnistä ( reusablePool ) thrd2 . Aloita ( reusable Pool ) ViewObject ( thisObject1 ) ViewObject ( thisObject2 ) lanka . Sleep ( 2000 ) reusablePool . Vapauta ( thisObject1 ) lanka . Sleep ( 2000 ) reusablePool . Vapauta ( thisObject2 ) konsoli . ReadKey () End Sub Yksityinen Jaettu Sub Run ( ByVal obj As [ Object ] ) - konsoli . WriteLine ( vbTab & System . Reflection . MethodInfo . GetCurrentMethod (. Nimi ) Dim reusablePool = DirectCast ( obj , ReusablePool ) konsoli . WriteLine ( vbTab & "aloitus odotus" ) Dim thisObject1 = reusablePool . WaitForObject () ViewObject ( thisObject1 ) - konsoli . WriteLine ( vbTab & "end wait" ) reusablePool . Release ( thisObject1 ) End Sub Yksityinen Jaettu Sub ViewObject ( ByVal thisObject uudelleenkäytettävänä ) Jokaiselle objektille Objektina tässä objektissa . _ _ _ Objs- konsoli . Kirjoita ( obj . ToString ( ) & " " ) Seuraava konsoli . WriteLine () End Sub End Class End Namespace

Perl esimerkki

Lähdeteksti Perlissä #!/usr/bin/perl -w =kommenttia varten ObjectPool-moduuli toteuttaa "objektipoolin" ohjelmointimallin simuloimalla jousiampujan käyttäytymistä, jolla on rajoitettu määrä nuolia nuolia nuolissaan, minkä seurauksena hänen on ajoittain poimittava niitä. Paketti kuvaa jousimiehen käyttäytymistä = leikattu paketti jousimies { käytä Quiveria ; #vire jousiampujan nuolilla käytä tiukkaa ; käytä varoituksia ; käytä vakiota ARROWS_NUMBER => 5 ; # nuolien määrä värinä käyttää vakiota SLEEP_TIME => 3 ; # enimmäistauko kahden toiminnon välillä (sekunneissa) # -- ** rakentaja ** -- sub new { minun $luokka = shift ; minun $self = { quiver => Quiver -> new ( ARROWS_NUMBER ), # objekti luokan "Quiver" }; siunaa $itse , $luokka ; palauttaa $self ; } # -- ** kuvauksen alustus ** -- sub shooting_start { my ( $self ) = ( shift ); while ( 1 ) { # ehdollisesti ääretön silmukka, joka ampuu $self -> shoot () for ( 0 .. rand ( ARROWS_NUMBER - 1 )); # satunnainen määrä laukauksia $itse -> lataa uudelleen () for ( 0 .. rand ( ARROWS_NUMBER - 1 )); # satunnainen määrä laukaistettujen nuolien palautusta } } # -- ** shot ** -- sub shoot { my ( $itse ) = ( shift ); $self -> { quiver } -> arrow_pull (); # lähetä nuoli helvettiin nukkumaan rand ( SLEEP_TIME ); # ... ja odota loputtomasti } # -- ** palauta laukaistu nuoli ** -- sub reload { my ( $self ) = ( shift ); $self -> { quiver } -> arrow_return (); # palauttaa aiemmin laukaistun nuolen uni - randin ( SLEEP_TIME ); # ja taas odotamme } } $jousimies = Jousimies - > uusi (); # rohkea jousiampuja ottaa nuolivilisensä $jousimies -> shooting_start (); # ... ja alkaa ampua =kommenttia varten Paketti kuvaa jousimiehen käyttämän nuolen ominaisuudet (Archer) ja johon nuolet on tallennettu (Arrow) = leikattu pakettivire { _ käytä Arrow ; # yksi nuoli nuolesta käytä ominaisuutta "sano" ; käytä tiukkaa ; käytä varoituksia ; # -- ** rakentaja ** -- sub new { oma ( $luokka , $nuolien_numero ) = ( shift , shift ); minun $self = { nuolet => [] , # nuolta värinä (ei vielä, mutta tulee pian) }; siunaa $itse , $luokka ; $self -> arrows_prepare ( $nuolien_numero ); # lataa nuolet quiveriin return $self ; } # -- ** valmistele nuolet ampumista varten ** -- sub arrows_prepare { my ( $itse , $nuolien_numero ) = ( shift , shift ); push @ { $self -> { arrows }}, Arrow -> new ( $_ ) for ( 0 .. $nuolien_numero - 1 ); # laita nuolet nuoliin } # -- ** vedä nuoli värinästä ** -- alanuoli_veto { oma ( $ itse ) = ( vaihto ); foreach ( @ { $self -> { arrows }}) { # jokaisen nuolen kohdalla tarkista, onko se värinä if ( $_ -> check_state ()) { # ja jos kyllä ​​$_ -> vedä (); # ota se pois sieltä (ja ammu) viimeisenä ; # emme voi laukaista kahta nuolta yhtä aikaa } } } # -- ** paluunuoli värinä ** -- alanuoli_paluu { oma ( $ itse ) = ( vaihto ); foreach ( @ { $self -> { arrows }}) { # jokaisen nuolen kohdalla tarkista, onko se jo laukaistu if ( ! $_ -> check_state ()) { # jos nuolta ei ole nuolivireessä $_ -> palauta ( ); # mene ja nouda se viimeisenä ; # teoriassa jousiampuja voi poimia useamman kuin yhden nuolen kerrallaan, mutta kirjoittaja ajattelee toisin } } } } 1 ; =kommenttia varten Paketti kuvaa jousiampujan nuolesta löytyvän nuolen ominaisuuksia (Archer) = leikattu paketti Arrow { käytä ominaisuutta "sano" ; käytä tiukkaa ; käytä varoituksia ; # -- ** rakentaja ** -- sub new { minun $luokka = shift ; $itseni = { numero = > vaihto , # nuolen numerotila => 1 , # nuolen tila (1 = värinä, 0 = makaa laukauksen jälkeen) } ; siunaa $itse , $luokka ; palauttaa $self ; } # -- ** poista nuoli nuolinäppäimestä ** -- sub pull { my ( $self ) = ( shift ); $itse -> { tila } = 0 ; # muuta nuolen tilaksi "vapautettu" sano "vedetty $self->{number}" ; # raportoi, että laukaus tapahtui } # -- ** laita nuoli takaisin nuoliin ** -- sub return { my ( $self ) = ( shift ); $itse -> { tila } = 1 ; # muuta nuolen tilaksi "väritetty" sano "palautti $self->{number}" ; # raportoi, että nuoli on palannut jousiampujaan } # -- ** tarkista nuolen tila ** -- alitarkistustila { oma ( $itse ) = ( shift ) ; return $self -> { tila }; # palauttaa nuolen tilan (1 = vapina, 0 = vapautettu) } } 1 ;

Linkit