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 .
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:
- Pool forlængelse.
- Afvisning af at oprette et objekt, nødstop.
- I tilfælde af et multitasking -system kan du vente, indtil et af objekterne er frigivet.
Eksempler
- Information om åbne filer i DOS .
- 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.
- 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
- 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 .
- 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.
- En flertrådet objektpulje er ikke let at skrive.
- 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
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 . få ( 'args' , [])
selv . _num_objects = max ( kwargs [ 'num' ], 0 )
self . _pred = kwargs [ 'update_func' ]
selv . _max_objects = kwargs . få ( '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 (); } } }
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 , så 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 () Få 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
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