Objekt pool

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 5. april 2022; checks kræver 4 redigeringer .
Objekt pool
objektpulje
Type genererer
Beskrevet i Design Patterns Ikke

En  objektpulje er et genererende designmønster , et sæt initialiserede og klar til brug objekter. Når systemet har brug for et objekt, bliver det ikke oprettet, men taget fra poolen. Når en genstand ikke længere er nødvendig, bliver den ikke ødelagt, men returneret til poolen.

Ansøgning

Objektpooling bruges til at forbedre ydeevnen, når du opretter et objekt i starten af ​​et job, og det er dyrt at ødelægge det i slutningen. Ydeevneforbedringen er især mærkbar, når objekter oprettes og ødelægges ofte, men kun et lille antal af dem eksisterer på samme tid.

En objektpulje er nyttig, når et objekt ejer andre ressourcer end hukommelse, såsom netværkssockets. Eller hvis samlingen af ​​objekter fylder en væsentlig del af computerens hukommelse og der skabes en masse " skrald ".

Overløb

Hvis der ikke er et enkelt ledigt objekt i puljen, er en af ​​tre strategier mulige:

  1. Pool forlængelse.
  2. Afvisning af at oprette et objekt, nødstop.
  3. I tilfælde af et multitasking -system kan du vente, indtil et af objekterne er frigivet.

Eksempler

  1. Information om åbne filer i DOS .
  2. Information om synlige objekter i mange computerspil ( Doom-motoren er et godt eksempel ). Denne information er kun relevant for én frame; efter at rammen er udlæst, tømmes listen.
  3. Et computerspil til lagring af alle objekter på kortet, i stedet for at bruge de sædvanlige hukommelsesallokeringsmekanismer, kan skabe et array af en sådan størrelse, at det vides at være nok til alle objekter, og beholde frie celler i form af en sammenkædet liste . Dette design forbedrer hastigheden, reducerer fragmentering af hukommelsen og reducerer belastningen på affaldssamleren (hvis nogen).

Traps

  1. Efter at en genstand er returneret, skal den vende tilbage til en tilstand, der er egnet til videre brug. Hvis genstande, efter at de er vendt tilbage til poolen, er i en forkert eller ubestemt tilstand, kaldes en sådan konstruktion en objektbrøndbrønd . 
  2. Genbrug af genstande kan også føre til informationslækage. Hvis objektet indeholder hemmelige data (for eksempel et kreditkortnummer ), efter at objektet er frigivet, skal disse oplysninger overskrives.
  3. En flertrådet objektpulje er ikke let at skrive.
  4. For 2020'erne er hukommelseshåndtering i skraldopsamlede sprog optimeret til konstant allokeringsrekyl. Så hvis objektet kun optager hukommelse, anbefaler Java-manualerne ikke at bruge puljer: en almindelig newkræver kun ti processorinstruktioner. Og skraldesamlere scanner ofte objektreferencer, ikke deres hukommelse - fordi jo flere "levende" objekter i hukommelsen, jo lavere ydeevne har en sådan samler.

Implementeringseksempel

Python- eksempel

Kildekode i Python #coding: utf-8 """ Lad os forestille os en situation, hvor vi har et skib, der kan modstå flere skud. At lave et Shot-objekt er dyrt. Derfor oprettes objekter fra Shot-familien én gang. Og efter levetiden forbliver objektet i hukommelse. """ klasse Skud ( objekt ): """En enhed, der kan overleve flere hits""" def __init__ ( selv , levetid = 5 ): selv . levetid = levetid def update ( selv ): selv . levetid -= 1 retur selv . levetid > 0 class ObjectPool : """Objektpulje""" def __init__ ( self , ** kwargs ): """Opretter puljen""" self . _clsname = kwargs [ 'klassenavn' ] selv . _args = kwargs . ( 'args' , []) selv . _num_objects = max ( kwargs [ 'num' ], 0 ) self . _pred = kwargs [ 'update_func' ] selv . _max_objects = kwargs . ( 'max' , self . _num_objects ) # Opret objekterne selv . _objs = [ anvend ( self . _clsname , self . _args ) for x in range ( self . _num_objects )] self . _end = len ( selv . _objs ) def _extend_list ( self , args ): """Tilføj et sted til puljen""" self . _objs . tilføj ( anvend ( selv . _clsnavn , args )) selv . _num_objekter += 1 def add ( self , * args ): """Tilføj et objekt til puljen""" newend = self . _end + 1 # Hvis maksimum er nået, læg på hvis newend > self . _max_objects : return None # Hvis alle pladser er taget, tilføj en plads mere hvis newend > len ( self . _objs ): self . _extend_list ( args ) andet : selv . _objs [ selv . _slut ] . nulstil ( * args ) selv . _end += 1 retur selv . _slut - 1 def update ( self , * args ): """Opdater alle objekter i puljen""" selv . _end = partition ( selv . _pred , self . _objs , 0 , self . _end , args ) returnerer selv . _ende def update_object ( x ): """Opdater objekt""" returnerer x . opdatering () def partition ( pred , seq , first , last , * args ): """Objektsorteringsfunktion""" if first > last : return 0 for i i området ( første , sidste ): hvis ikke pred ( seq [ i ]): break else : returner sidst for j i interval ( i + 1 , sidste ): if pred ( seq [ j ]): seq [ i ], seq [ j ] = seq [ j ], seq [ i ] i += 1 return i # Bruger faktisk pool shots = ObjectPool ( klassenavn = Shot , update_func = update_object , num = 5 ) mens skud . opdatering (): bestå print "Udført!"

C++ eksempel

Kildetekst i C++ #inkluder <vektor> klasse Objekt { // ... }; klasse ObjectPool { privat : strukturer PoolRecord { objekt * instans ; bool in_use ; }; std :: vektor < PoolRecord > m_pool ; offentligt : Objekt * createNewObject () { for ( størrelse_t i = 0 ; i < m_pulje . størrelse (); ++ i ) { if ( ! m_pool [ i ]. i_brug ) { m_pool [ i ]. in_use = sand ; // overfør objektet til listen over brugte returner m_pool [ i ]. instans ; } } // hvis vi ikke fandt et ledigt objekt, så udvide poolen PoolRecord record ; optage . instans = nyt objekt ; optage . in_use = sand ; m_pool . push_back ( rekord ); returnere rekord . instans ; } void deleteObject ( Objekt * objekt ) { // i virkeligheden sletter vi ikke, men markerer kun at objektet er ledigt for ( size_t i = 0 ; i < m_pool . size (); ++ i ) { if ( m_pool [ i ]. instans == objekt ) { m_pool [ i ]. in_use = falsk ; bryde ; } } } virtuel ~ ObjectPool () { // nu sletter vi "virkelig" objekter for ( size_t i = 0 ; i < m_pool . size (); ++ i ) slet m_pool [ i ]. instans ; } }; int main () { Objektpulje ; _ for ( størrelse_t i = 0 ; i < 1000 ; ++ i ) { Objekt * objekt = pulje . createNewObject (); // ... pool . deleteObject ( objekt ); } returnere 0 ; }

Skabeloner og trådsikkerhed er blevet fjernet fra eksemplet for nemheds skyld . Hvis du skal bruge puljen på tværs af flere tråde, bør du beskytte kroppen af ​​createNewObject og deleteObject-metoderne mod samtidig udførelse af et passende synkroniseringsobjekt, såsom en kritisk sektion eller en mutex .

Eksempel i C#

Kildetekst i C# navneområde Digital_Patterns.Creational.Object_Pool.Soft { /// <summary> /// Interface til brug af "Object Pool"-mønsteret <see cref="Object_Pool"/> /// </summary> /// <typeparam name= " T"></typeparam> offentlig grænseflade ICreation < T > { /// <summary> /// Returnerer det nyoprettede objekt /// </summary> /// <returns></returns> T Opret () ; } } Kildetekst i C# bruger System ; ved hjælp af System.Collections ; ved hjælp af System.Threading ; navneområde Digital_Patterns.Creational.Object_Pool.Soft { /// <summary> /// Implementering af en objektpulje ved hjælp af bløde referencer /// </summary> /// <typeparam name="T"></typeparam> public class ObjectPool < T > hvor T : klasse { /// <resumé> /// Synkroniseringsobjekt /// </summary> privat semafor semafor ; /// <summary> /// Samlingen indeholder administrerede objekter /// </summary> private ArrayList pool ; /// <resumé> /// Reference til det objekt, som ansvaret /// for at skabe puljens objekter er uddelegeret til /// </summary> private ICreation < T > creator ; /// <summary> /// Antallet af objekter, der i øjeblikket eksisterer /// </summary> private Int32 instanceCount ; /// <summary> /// Maksimalt antal objekter administreret af puljen /// </summary> private Int32 maxInstances ; /// <summary> /// Oprettelse af en objektpulje /// </summary> /// <param name="creator">Det objekt, som puljen vil delegere ansvaret til /// for at oprette de objekter, den administrerer< /param> public ObjectPool ( ICreation < T > creator ) : denne ( creator , Int32 . MaxValue ) { } /// <summary> /// Oprettelse af en objektpulje /// </summary> /// <param name="creator">Det objekt, som puljen vil delegere ansvaret til /// for at oprette de objekter, den administrerer< /param> / // <param name="maxInstances">Det maksimale antal klasseforekomster /// som puljen tillader at eksistere på samme tid /// </param> public ObjectPool ( ICreation < T > creator , Int32 maxInstances ) { this . skaber = skaber ; dette . instanceCount = 0 ; dette . maxInstances = maxInstances ; dette . pool = ny ArrayList (); dette . semafor = ny semafor ( 0 , denne . maxInstances ); } /// <resumé> /// Returnerer antallet af objekter i puljen, der venter på at blive /// genbrugt. Det faktiske antal /// kan være mindre end denne værdi, fordi /// den returnerede værdi er antallet af bløde referencer i puljen. /// </summary> public Int32 Størrelse { get { lock ( pool ) { returner pool . tælle ; } } } /// <summary> /// Returnerer antallet af poolede objekter ///, der i øjeblikket eksisterer /// </summary> public Int32 InstanceCount { get { return instanceCount ; } } /// <resumé> /// Hent eller indstil det maksimale antal /// administrerede objekter, som puljen tillader at eksistere på samme tid. /// </summary> public Int32 MaxInstances { get { return maxInstances ; } sæt { maxInstances = værdi ; } } /// <resumé> /// Returnerer et objekt fra puljen. Med en tom pulje vil et /// objekt blive oprettet, hvis antallet af objekter /// administreret af puljen ikke er større end eller lig med værdien /// returneret af <see cref="ObjectPool{T}. MaxInstances"/> metode. Hvis antallet af objekter /// administreret af puljen overstiger denne værdi, returnerer denne metode null /// </summary> /// <returns></returns> public T GetObject () { lock ( pool ) { T thisObject = RemoveObject ( ); if ( detteObject != null ) returner detteObjekt ; if ( InstanceCount < MaxInstances ) returner CreateObject (); returner null ; } } /// <resumé> /// Returnerer et objekt fra puljen. Med en tom pulje vil et /// objekt blive oprettet, hvis antallet af objekter /// administreret af puljen ikke er større end eller lig med værdien /// returneret af <see cref="ObjectPool{T}. MaxInstances"/> metode. Hvis antallet af objekter /// administreret af puljen overstiger denne værdi, vil denne metode vente indtil /// indtil et objekt bliver tilgængeligt til /// genbrug. /// </summary> /// <returns></returns> public T WaitForObject () { lock ( pool ) { T thisObject = RemoveObject (); if ( detteObject != null ) returner detteObjekt ; if ( InstanceCount < MaxInstances ) returner CreateObject (); } semafor . waitone (); returner WaitForObject (); } /// <summary> /// Fjerner et objekt fra poolsamlingen og returnerer det /// </summary> /// <returns></returns> private T RemoveObject () { while ( pool . Count > 0 ) { var refThis = ( WeakReference ) pool [ pool . Antal - 1 ]; pool . RemoveAt ( pulje . Count - 1 ); var thisObject = ( T ) refThis . Mål ; if ( detteObject != null ) returner detteObjekt ; instanceCount --; } returner null ; } /// <resumé> /// Opret et objekt, der administreres af denne pulje /// </summary> /// <returns></returns> privat T CreateObject () { T newObject = creator . oprette (); instanceCount ++; returnere nyt objekt ; } /// <summary> /// Frigør objektet, placerer det i puljen til /// genbrug /// </summary> /// <param name="obj"></param> /// <exception cref ="NullReferenceException"></exception> public void Release ( T obj ) { if ( obj == null ) throw new NullReferenceException (); lock ( pool ) { var refThis = new WeakReference ( obj ); pool . Tilføj ( refThis ); semafor . frigivelse (); } } } } Kildetekst i C# navneområde Digital_Patterns.Creational.Object_Pool.Soft { public class Genbrugelig { public Object [] Objs { get ; beskyttet sæt ; } public Genbrugelig ( params Object [] objs ) { this . Objs = objs ; } } public class Creator : ICreation < Genbrugelig > { private static Int32 iD = 0 ; public Genbrugelig Opret () { ++ iD ; returnere ny Genanvendelig ( iD ); } } public class ReusablePool : ObjectPool < Genanvendelig > { public ReusablePool () : base ( new Creator (), 2 ) { } } } Kildetekst i C# bruger System ; ved hjælp af System.Threading ; ved hjælp af Digital_Patterns.Creational.Object_Pool.Soft ; navneområde Digital_Patterns { class Program { static void Main ( string [ ] args ) { Console . WriteLine ( System . Reflection . MethodInfo . GetCurrentMethod (). Navn ); var reusablePool = new ReusablePool (); var thrd1 = ny tråd ( Kør ); var thrd2 = ny tråd ( Kør ); var thisObject1 = genanvendeligPool . GetObject (); var thisObject2 = genanvendeligPool . GetObject (); thrd1 . Start ( genanvendelig Pool ); thrd2 . Start ( genanvendelig Pool ); ViewObject ( detteObject1 ); ViewObject ( detteObject2 ); tråd . Søvn ( 2000 ); genanvendelig Pool . Frigivelse ( detteObject1 ); tråd . Søvn ( 2000 ); genanvendelig Pool . Frigiv ( detteObject2 ); Konsol . ReadKey (); } private static void Kør ( Object obj ) { Console . WriteLine ( "\t" + System . Reflektion . MethodInfo . GetCurrentMethod (). Navn ); var reusablePool = ( ReusablePool ) obj ; Konsol . WriteLine ( "\tstart vent" ); var thisObject1 = genanvendeligPool . WaitForObject (); ViewObject ( detteObject1 ); Konsol . WriteLine ( "\tend wait" ); genanvendelig Pool . Frigiv ( detteObject1 ); } private static void ViewObject ( genanvendelig detteObject ) { foreach ( var obj in thisObject . Objs ) { Console . Skriv ( obj . ToString () + @" " ); } Konsol . skriveLine (); } } }

VB.NET eksempel

Kildetekst på VB.NET sprog Navneområde Digital_Patterns.Creational.Object_Pool.Soft ' Interface til at bruge "Object Pool" skabelonen <see cref="Object_Pool"/> Public Interface ICreation ( Of T ) ' Returnerer det nyoprettede objekt Funktion Create () As T End Interface afslutte navneområde Kildetekst på VB.NET sprog Navneområde Digital_Patterns.Creational.Object_Pool.Soft 'Implementering af objektpulje ved hjælp af bløde referencer Public Class ObjectPool ( Of T As Class ) 'Synkroniser objekt Privat semafor Som semafor 'Samlingen indeholder administrerede objekter Privat pool Som ArrayList 'Reference til det objekt, som ansvaret for at skabe puljens objekter Privat skaberen Som ICreation ( Af T ) er delegeret til 'Antal objekter i øjeblikket eksisterende Private m_instanceCount As Int32 'Maksimalt antal poolede objekter Private m_maxInstances As Int32 'Object Pool Creation' -skaber er det objekt, som puljen vil uddelegere ansvaret for at skabe de objekter, den administrerer Public Sub New ( ByVal creator As ICreation ( Of T )) Me . Ny ( skaber , Int32 . MaxValue ) End Sub 'Creating an object pool ' creator - Objektet, som puljen vil delegere ansvaret for at oprette de objekter, den administrerer til ' maxInstances - Det maksimale antal forekomster af klassen, som puljen vil tillade at eksistere på samme tid Public Sub New ( ByVal skaberen Som ICreation ( Af T ), ByVal maxInstances As Int32 ) mig . skaber = skaber Mig . m_instanceCount = 0 Mig . m_maxInstances = maxInstances Me . pool = New ArrayList () Mig . semafor = Ny semafor ( 0 , Me . m_maxInstances ) End Sub 'Returnerer antallet af genstande i poolen, der venter på at blive genbrugt . Det faktiske antal kan være mindre end denne 'værdi, fordi den returnerede værdi er' antallet af bløde referencer i puljen. Offentlig skrivebeskyttet ejendomsstørrelse ( ) Som Int32 Hent SyncLock pool Returpulje . _ Count End SyncLock End Hent End Property 'Returnerer antallet af poolede objekter, der aktuelt eksisterer' Public ReadOnly Property InstanceCount () As Int32 Get Return m_instanceCount End Get End Property 'Få eller indstil det maksimale antal pulje-administrerede ' objekter, som puljen tillader at eksistere på ethvert tidspunkt. Public Property MaxInstances () As Int32 Get Return m_maxInstances End Get Set ( ByVal value As Int32 ) m_maxInstances = værdi End Set End Property 'Returnerer en genstand fra poolen. En tom pulje vil skabe et 'objekt, hvis antallet af objekter, der administreres af puljen, ikke er større end eller lig med den værdi, der returneres af metoden ObjectPool{T}.MaxInstances. ' Hvis antallet af poolede objekter overstiger denne værdi, returnerer denne 'metode null Public Function GetObject () As T SyncLock pool Dim thisObject As T = RemoveObject () If thisObject IsNothing Then Return thisObject End If Hvis InstanceCount < MaxInstances Returner derefter CreateObject () End If Returner intet End SyncLock End - funktion ' Returnerer et objekt fra puljen. En tom pulje vil oprette et ' objekt, hvis antallet af poolede objekter ' ikke er større end eller lig med værdien returneret af ObjectPool{T}.MaxInstances-metoden ' Hvis antallet af poolede objekter overstiger denne værdi, ' vil denne metode vente indtil objektet ' ikke bliver gjort tilgængeligt til genbrug. Offentlig funktion WaitForObject () As T SyncLock pool Dim thisObject As T = RemoveObject () If thisObject IsNothing . Returner derefter detteObject End If Hvis InstanceCount < MaxInstances Returner derefter CreateObject () End If End SyncLock semafor . WaitOne () Returner WaitForObject () End Function ' Fjerner et objekt fra poolsamlingen og returnerer det Private Function RemoveObject () As T While pool . Count > 0 Dim refThis = DirectCast ( pulje ( pulje . Count - 1 ), WeakReference ) pulje . RemoveAt ( pool . Count - 1 ) Dim thisObject = DirectCast ( refThis . Target , T ) If thisObject IsNothing Then Return thisObject End If m_instanceCount - = 1 End While Return Nothing End Function ' Opret et objekt, der administreres af denne pulje Privat funktion CreateObject () As T Dim newObject As T = creator . Opret () m_instanceCount += 1 Returner newObject End Function ' Frigiver objektet og placerer det i puljen til genbrug Offentlig underudgivelse ( ByVal obj As T ) Hvis obj er ingenting , Kast ny NullReferenceException ( ) End If SyncLock pool Dim refThis = New WeakReference ( obj ) pool . Tilføj ( refThis ) semafor . Slip () End SyncLock End Sub End Class End Namespace Kildetekst på VB.NET sprog Navneområde Digital_Patterns.Creational.Object_Pool.Soft '### Klasse Genanvendelig #### Offentlig Klasse Genanvendelig Private m_Objs som objekt () Public Sub New ( ByVal ParamArray objs As Object ()) Me . Objs = objs End Sub Offentlig ejendomsobj . () Som objekt () retur m_Objs End Get Beskyttet sæt ( ByVal værdi som objekt ( ) ) m_Objs = værdi Slutsæt Slutegenskab Slutklasse _ '### Class Creator #### Public Class Creator implementerer ICreation ( af genbrugelig ) Privat delt ID som Int32 = 0 Offentlig funktion Opret () Som genanvendelige implementerer ICreation ( Af genbrugelig ). Opret iD + = 1 Returner Ny Genbrugelig ( iD ) Slutfunktion Slutklasse _ '### ReusablePool Class #### Public Class ReusablePool arver ObjectPool ( Of Reusable ) Offentlig Sub Ny () MyBase . Ny ( New Creator (), 2 ) End Sub End Class End Namespace Kildetekst på VB.NET sprog Importerer System.Threading Importerer Digital_Patterns.Creational.Object_Pool.Soft Navneområde Digital_Patterns Klasseprogram _ Delt underhovedkonsol ( ) . _ WriteLine ( System . Reflection . MethodInfo . GetCurrentMethod ( ). Navn ) Dim reusablePool = New ReusablePool () Dim thrd1 = Ny tråd ( Kørselsadresse ) Dim thrd2 = Ny tråd ( Kørselsadresse ) Dæmp thisObject1 = genbrugbar Pool . _ GetObject () Dim thisObject2 = genanvendeligPool . GetObject () thrd1 . Start ( genanvendelig pool ) thrd2 . Start ( genanvendelig pool ) ViewObject ( thisObject1 ) ViewObject ( thisObject2 ) tråd . Sleep ( 2000 ) genanvendelig Pool . Frigivelse ( detteObject1 ) tråd . Sleep ( 2000 ) genanvendelig Pool . Frigivelse ( thisObject2 ) Konsol . ReadKey () End Sub Privat delt underkørsel ( ByVal obj As [ Object ] ) konsol . _ WriteLine ( vbTab & System . Reflection . MethodInfo . GetCurrentMethod (. Navn ) Dim reusablePool = DirectCast ( obj , ReusablePool ) Konsol . WriteLine ( vbTab & "start vente" ) Dim thisObject1 = genanvendeligPool . WaitForObject () ViewObject ( thisObject1 ) Console . WriteLine ( vbTab & "end wait" ) genbrugbar Pool . Frigiv ( thisObject1 ) End Sub Private Shared Sub ViewObject ( ByVal thisObject As Genanvendeligt ) For hver obj As Object In thisObject . Objs konsol . Skriv ( obj . ToString () & " " ) Næste konsol . WriteLine () End Sub End Class End Namespace

Perl- eksempel

Kildetekst i Perl #!/usr/bin/perl -w =til kommentar ObjectPool-modulet implementerer "objektpuljen"-programmeringsmønsteret ved at simulere adfærden hos en bueskytte, der har et begrænset antal pile i sit kogger, som et resultat af hvilket han periodisk skal samle dem op Pakken beskriver bueskyttens adfærd = skære pakke bueskytte { brug Quiver ; # kogger med bueskytterpile brug streng ; brug advarsler ; brug konstant ARROWS_NUMBER => 5 ; # antal pile i koggeret bruger konstant SLEEP_TIME => 3 ; # maksimal pause mellem to handlinger (i sekunder) # -- ** constructor ** -- sub new { my $class = shift ; mit $selv = { quiver => Quiver -> new ( ARROWS_NUMBER ), # objekt i klassen "Quiver" }; velsigne $selv , $klasse ; returnere $selv ; } # -- ** shooting initialization ** -- sub shooting_start { my ( $self ) = ( shift ); while ( 1 ) { # betinget uendelig løkke, der skyder $self -> shoot () for ( 0 .. rand ( ARROWS_NUMBER - 1 )); # tilfældigt antal skud $self -> genindlæs () for ( 0 .. rand ( ARROWS_NUMBER - 1 )); # tilfældigt antal returneringer af affyrede pile } } # -- ** skud ** -- sub shoot { my ( $self ) = ( shift ); $self -> { quiver } -> arrow_pull (); # send pilen til helvede søvn rand ( SLEEP_TIME ); # ... og vent på ubestemt tid } # -- ** returnerer den affyrede pil ** -- sub reload { my ( $self ) = ( shift ); $selv -> { kogger } -> arrow_return (); # returner den tidligere affyrede pil sleep rand ( SLEEP_TIME ); # og igen venter vi } } $archer = Archer -> new (); # den modige bueskytte tager sit pilkogger $archer -> shooting_start (); # ... og begynder at skyde =til kommentar Pakken beskriver egenskaberne for koggeren, der bruges af bueskytten (Archer), og hvori pilene er gemt (Arrow) = skære pakke quiver { brug pil ; # én pil fra koggeren brug funktionen "sig" ; brug streng ; brug advarsler ; # -- ** constructor ** -- sub new { my ( $ class , $ arrows_number ) = ( shift , shift ); mit $selv = { pile => [] , # pile i kogger (ikke endnu, men kommer snart) }; velsigne $selv , $klasse ; $self -> arrows_prepare ( $arrows_number ); # indlæs pile i kogger return $self ; } # -- ** forbered pile til skydning ** -- sub arrows_prepare { my ( $self , $ arrows_number ) = ( shift , shift ); push @ { $self -> { arrows }}, Arrow -> new ( $_ ) for ( 0 .. $ arrows_number - 1 ); # sæt pilene i koggeren } # -- ** træk pil fra kogger ** -- sub arrow_pull { min ( $selv ) = ( skift ); foreach ( @ { $self -> { arrows }}) { # for hver pil, tjek om den er i koggeren if ( $_ -> check_state ()) { # og hvis ja $_ -> pull (); # tag den ud derfra (og skyd) sidst ; # vi kan ikke affyre to pile på samme tid } } } # -- ** returpil til kogger ** -- sub arrow_return { min ( $selv ) = ( skift ); foreach ( @ { $self -> { arrows }}) { # for hver pil, tjek om den allerede er blevet affyret if ( ! $_ -> check_state ()) { # hvis der ikke er en sådan pil i koggeren $_ -> retur ( ); # gå hen og hent den sidst ; # i teorien kan en bueskytte tage mere end én pil ad gangen, men forfatteren mener noget andet } } } } 1 ; =til kommentar Pakken beskriver egenskaberne af en enkelt pil fundet i koggeret på en bueskytte (Archer) = skære pakke Arrow { brug funktionen "sig" ; brug streng ; brug advarsler ; # -- ** constructor ** -- sub new { my $class = shift ; mit $selv = { nummer => skift , # pil nummer tilstand => 1 , # pil tilstand (1 = i kogger, 0 = liggende efter skud) }; velsigne $selv , $klasse ; returnere $selv ; } # -- ** fjern pil fra kogger ** -- sub pull { my ( $self ) = ( shift ); $self -> { state } = 0 ; # skift piltilstand til "frigivet" sig "trukket $selv->{nummer}" ; # rapporterer, at skuddet fandt sted } # -- ** sæt pilen tilbage i koggeren ** -- sub return { my ( $self ) = ( shift ); $self -> { state } = 1 ; # skift piletilstand til "quivered" sig " returned $self->{number}" ; # rapporter at pilen er vendt tilbage til bueskytten } # -- ** check arrow state ** -- sub check_state { my ( $self ) = ( shift ); returner $self -> { state }; # returner pilens tilstand (1 = dirrende, 0 = frigivet) } } 1 ;

Links