Tárgykészlet
Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2022. április 5-én felülvizsgált
verziótól ; az ellenőrzések 4 szerkesztést igényelnek .
Az objektumkészlet egy generáló tervezési minta , inicializált és használatra kész objektumok halmaza. Amikor a rendszernek szüksége van egy objektumra, az nem jön létre, hanem kiveszi a készletből. Amikor egy tárgyra már nincs szükség, nem semmisül meg, hanem visszakerül a medencébe.
Alkalmazás
Az objektumkészletezést a teljesítmény javítására használják, amikor egy objektum létrehozása a feladat elején, és a végén megsemmisítése költséges. A teljesítménynövekedés különösen akkor észrevehető, ha az objektumokat gyakran hoznak létre és semmisítik meg, de egyszerre csak kevés van belőlük.
Az objektumkészlet akkor hasznos, ha egy objektum a memórián kívül más erőforrásokkal is rendelkezik, például hálózati socketekkel. Vagy ha az objektumok gyűjteménye a számítógép memóriájának jelentős részét elfoglalja, és sok " szemét " keletkezik.
Túlcsordulás
Ha nincs egyetlen szabad objektum sem a készletben, három stratégia egyike lehetséges:
- Medence bővítés.
- Objektum létrehozásának megtagadása, vészleállítás.
- Többfeladatos rendszer esetén megvárhatja, amíg az egyik objektum felszabadul.
Példák
- Információ a DOS-ban megnyitott fájlokról .
- Információk sok számítógépes játékban látható tárgyakról ( jó példa a Doom motor ). Ez az információ csak egy keretre vonatkozik; a keret kiadása után a lista kiürül.
- Egy számítógépes játék, amely az összes objektumot a térképen tárolja, a szokásos memóriakiosztási mechanizmusok használata helyett olyan méretű tömböt tud létrehozni, amelyről ismert, hogy minden objektum számára elegendő, és a szabad cellákat linkelt lista formájában megtartja. . Ez a kialakítás javítja a sebességet, csökkenti a memória töredezettségét és csökkenti a szemétgyűjtő terhelését (ha van ilyen).
Csapdák
- Egy tárgy visszaküldése után vissza kell térnie a további használatra alkalmas állapotba. Ha az objektumok a készletbe való visszatérés után hibás vagy határozatlan állapotban vannak, az ilyen konstrukciót objektumtárolónak nevezzük .
- A tárgyak újrafelhasználása információszivárgáshoz is vezethet. Ha az objektum titkos adatokat tartalmaz (például hitelkártyaszám ), az objektum kiadása után ezeket az információkat felül kell írni.
- Egy többszálú objektumkészletet nem könnyű írni.
- A 2020-as évekre a hulladékgyűjtő nyelveken a memóriakezelés jól optimalizált az állandó kiosztás-visszarúgáshoz. Tehát, ha az objektum csak memóriát foglal el, a Java kézikönyvek nem javasolják a poolok használatát: egy newnormálhoz mindössze tíz processzorutasítás szükséges. És a szemétgyűjtők gyakran az objektum-hivatkozásokat vizsgálják, nem a memóriájukat - mert minél több „élő” objektum van a memóriában, annál alacsonyabb egy ilyen gyűjtő teljesítménye.
Megvalósítási példa
Forráskód Pythonban
#kódolás: utf-8
""" Képzeljünk
el egy olyan helyzetet, ahol van egy hajónk, amely több lövést is kibír.
A Shot objektum létrehozása költséges.
Ezért a Shot család objektumai egyszer jönnek létre.
És az élettartam után az objektum benne marad memória.
"""
osztály Shot ( objektum ):
"""Olyan entitás, amely több találatot is túlél"""
def __init__ ( self , lifetime = 5 ):
self . élettartam = élettartam
def update ( self ):
self . élettartam -= 1
visszatérő én . élettartam > 0
class ObjectPool :
"""Object Pool"""
def __init__ ( self , ** kwargs ):
"""A készlet létrehozása"""
self . _clsname = kwargs [ 'osztálynév' ]
self . _args = kwargs . get ( 'args' , [])
self . _num_objects = max ( kwargs [ 'szám' ], 0 )
self . _pred = kwargs [ 'update_func' ]
self . _max_objects = kwargs . get ( 'max' , self . _num_objects )
# Saját objektumok létrehozása . _objs = [ alkalmaz ( self . _clsname , self . _args )
for x in range ( self . _num_objects )]
self . _end = len ( self . _objs )
def _extend_list ( self , args ):
"""Egy hely hozzáadása a készlethez"""
self . _objs . append ( alkalmaz ( self . _clsname , args ))
self . _objektumok száma += 1
def add ( self , * args ):
"""Egy objektum hozzáadása a készlethez"""
newend = self . _end + 1
# Ha elérte a maximumot, tegye le,
ha newend > self . _max_objects :
return Nincs
# Ha minden hely foglalt, adjon hozzá még egy helyet
if newend > len ( self . _objs ):
self . _extend_list ( args )
else :
self . _objs [ self . _end ] . reset ( * args )
self . _end += 1
önmagát adja vissza . _end - 1
def update ( self , * args ):
"""A készlet összes objektumának frissítése"""
self . _end = partíció ( self . _pred , self . _objs , 0 , self . _end , args )
önmagát adja vissza . _end
def update_object ( x ):
"""Objektum frissítése"""
return x . frissítés ()
def partíció ( pred , seq , first , last , * args ):
"""Objektumrendezési függvény"""
if first > last :
return 0
for i in range ( first , last ):
ha nem pred ( seq [ i ] ):
break
else :
return last
j esetén az ( i + 1 , utolsó ) tartományban : ha pred ( seq [ j ]): seq [ i ], seq [ j ] = seq [ j ], seq [ i ] i += 1 visszatér i
# Valójában a pool
shots = ObjectPool ( osztálynév = Shot , update_func = update_object , num = 5 ) használata a shots közben . frissítés (): passz
nyomtatni "Kész!"
Forrásszöveg C++ nyelven
#include <vektor>
osztály Objektum
{
// ...
};
osztályú ObjectPool
{
privát :
struct PoolRecord
{
objektum * példány ;
bool in_use ;
};
std :: vektor < PoolRecord > m_pool ;
nyilvános :
Object * CreateNewObject ()
{
for ( size_t i = 0 ; i < m_pool . size (); ++ i )
{
if ( ! m_pool [ i ]. in_use )
{
m_pool [ i ]. in_use = igaz ; // az objektum átvitele a használtak listájába return m_pool [ i ]. példány ;
}
}
// ha nem találtunk szabad objektumot, akkor bontsa ki a
poolRecord rekordot ;
rekord . példány = new Object ;
rekord . in_use = igaz ;
m_pool . push_back ( rekord );
visszatérési rekord . példány ;
}
void deleteObject ( objektum * objektum )
{
// a valóságban nem töröljük, hanem csak azt jelöljük meg, hogy az objektum szabad
a számára ( size_t i = 0 ; i < m_pool . size (); ++ i )
{
if ( m_pool [ i ]. példány == objektum )
{
m_pool [ i ]. in_use = false ;
szünet ;
}
}
}
virtuális ~ ObjectPool ()
{
// most "igazán" töröljük az objektumokat
a következőhöz: ( size_t i = 0 ; i < m_pool . size (); ++ i )
az m_pool [ i ] törlése . példány ;
}
};
int main ()
{
Object Pool ;
for ( méret_t i = 0 ; i < 1000 ; ++ i )
{
Object * object = pool . CreateNewObject ();
// ...
medence . deleteObject ( objektum );
}
return 0 ;
}
A sablonokat és a szálbiztonságot az egyszerűség kedvéért eltávolítottuk a példából . Ha több szálon keresztül kell használnia a készletet, védje meg a createNewObject és deleteObject metódusok törzsét egy megfelelő szinkronizálási objektum, például kritikus szakasz vagy mutex egyidejű végrehajtásától .
Forrásszöveg C# nyelven
névtér Digital_Patterns.Creational.Object_Pool.Soft
{
/// <summary>
/// Interfész az "Object Pool" minta használatához <see cref="Object_Pool"/>
/// </summary>
/// <typeparam name= " T"></typeparam>
nyilvános felület ICreation < T >
{
/// <summary>
/// Visszaadja az újonnan létrehozott objektumot
/// </summary>
/// <returns></returns>
T Létrehoz () ;
}
}
Forrásszöveg C# nyelven
a rendszer használatával ;
a System.Collections használatával ;
a System.Threading használatával ;
névtér Digital_Patterns.Creational.Object_Pool.Soft
{
/// <summary>
/// Objektumkészlet megvalósítása soft referenciák segítségével
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObjectPool < T > ahol T : class
{
/// <summary>
/// Szinkronizálási objektum
/// </summary>
private szemafor szemafor ;
/// <summary>
/// A gyűjtemény kezelt objektumokat tartalmaz
/// </summary>
private ArrayList pool ;
/// <summary>
/// Hivatkozás arra az objektumra, amelyre
/// a készlet objektumainak létrehozásának felelőssége delegálva
/// </summary>
private ICreation < T > creator ;
/// <summary>
/// A jelenleg létező objektumok száma
/// </summary>
private Int32 instanceCount ;
/// <summary>
/// A készlet által kezelt objektumok maximális száma
/// </summary>
private Int32 maxInstances ;
/// <summary>
/// Objektumkészlet létrehozása
/// </summary>
/// <param name="creator">Az objektum, amelyre a készlet átruházza a felelősséget
/// az általa kezelt objektumok létrehozásáért< /param>
public ObjectPool ( ICreation < T > creator )
: this ( creator , Int32 . MaxValue )
{
}
/// <summary>
/// Objektumkészlet létrehozása
/// </summary>
/// <param name="creator">Az objektum, amelyre a készlet átruházza a felelősséget
/// az általa kezelt objektumok létrehozásáért< /param>
/ // <param name="maxInstances">Az osztálypéldányok maximális száma
///, amelyet a készlet engedélyez egyidejűleg
/// </param>
public ObjectPool ( ICreation < T > creator , Int32 maxInstances )
{
this . alkotó = alkotó ;
ezt . példányszám = 0 ;
ezt . maxInstances = maxInstances ;
ezt . pool = new ArrayList ();
ezt . szemafor = new Semaphore ( 0 , this . maxInstances );
}
/// <összefoglaló>
/// Visszaadja a készletben lévő objektumok számát, amelyek
újrafelhasználásra várnak ///. A tényleges szám
/// kisebb lehet ennél az értéknél, mert
/// a visszaadott érték a készletben lévő soft referenciák száma.
/// </summary>
public Int32 Size
{
get
{
lock ( pool )
{
return pool . gróf ;
}
}
}
/// <summary> /// Visszaadja a
jelenleg létező egyesített objektumok számát ///
/// </summary> public Int32 InstanceCount { get { return instanceCount ; } }
/// <összefoglaló>
/// Szerezze be vagy állítsa be a felügyelt objektumok /// maximális számát,
amelyet a készlet egyidejűleg engedélyez.
/// </summary>
public Int32 MaxInstances
{
get { return maxInstances ; }
set { maxInstances = érték ; }
}
/// <összefoglaló>
/// Egy objektumot ad vissza a készletből. Üres készlet esetén
/// objektum jön létre, ha a
készlet által kezelt objektumok /// száma nem nagyobb vagy egyenlő, mint
a <see cref="ObjectPool{T} /// által visszaadott érték. MaxInstances"/> metódus. Ha a készlet által kezelt objektumok száma ///
meghaladja ezt az értéket, akkor ez a metódus null értékkel tér vissza
/// </summary>
/// <returns></returns>
public T GetObject ()
{
lock ( pool )
{
T thisObject = RemoveObject ( );
if ( thisObject != null )
return thisObject ;
if ( InstanceCount < MaxInstances )
return CreateObject ();
return null ;
}
}
/// <összefoglaló>
/// Egy objektumot ad vissza a készletből. Üres készlet esetén
/// objektum jön létre, ha a
készlet által kezelt objektumok /// száma nem nagyobb vagy egyenlő, mint
a <see cref="ObjectPool{T} /// által visszaadott érték. MaxInstances"/> metódus. Ha a készlet által kezelt objektumok /// száma
meghaladja ezt az értéket, akkor ez a metódus addig vár,
amíg egy objektum
/// újrafelhasználhatóvá válik.
/// </summary>
/// <returns></returns>
public T WaitForObject ()
{
lock ( pool )
{
T thisObject = RemoveObject ();
if ( thisObject != null )
return thisObject ;
if ( InstanceCount < MaxInstances )
return CreateObject ();
}
szemafor . várakozó ();
return WaitForObject ();
}
/// <summary>
/// Eltávolít egy objektumot a készletgyűjteményből, és visszaadja
/// </summary>
/// <returns></returns>
private T RemoveObject ()
{
while ( pool . Count > 0 )
{
var refThis = ( WeakReference ) pool [ pool . Szám - 1 ];
medence . RemoveAt ( pool . Count - 1 );
var thisObject = ( T ) refThis . Cél ;
if ( thisObject != null )
return thisObject ;
instanceCount --;
}
return null ;
}
/// <summary>
/// A készlet által kezelt objektum létrehozása
/// </summary>
/// <returns></returns>
private T CreateObject ()
{
T newObject = creator . létrehozni ();
instanceCount ++;
return newObject ;
}
/// <summary>
/// Felszabadítja az objektumot, a készletbe helyezve
/// újrafelhasználásra
/// </summary>
/// <param name="obj"></param>
/// <kivétel cref ="NullReferenceException"></exception>
public void Release ( T obj )
{
if ( obj == null )
throw new NullReferenceException ();
lock ( pool )
{
var refThis = new WeakReference ( obj );
medence . Add ( refThis );
szemafor . kiadás ();
}
}
}
}
Forrásszöveg C# nyelven
névtér Digital_Patterns.Creational.Object_Pool.Soft
{
public class Újrafelhasználható
{
public Object [] Objs { get ; védett készlet ; }
public Újrafelhasználható ( params Object [ ] objs )
{
this . Objs = objs ;
}
}
public class Létrehozó : ICreation < Reusable >
{
private static Int32 iD = 0 ;
public Újrafelhasználható Létrehoz ()
{
++ iD ;
új újrafelhasználható ( iD ) visszaküldése ; } }
public class ReusablePool : ObjectPool < Reusable >
{
public ReusablePool ()
: base ( new Creator (), 2 )
{
}
}
}
Forrásszöveg C# nyelven
a rendszer használatával ;
a System.Threading használatával ;
a Digital_Patterns.Creational.Object_Pool.Soft használatával ;
névtér Digital_Patterns
{
class Program
{
static void Main ( string [ ] args )
{
Console . WriteLine ( System . Reflection . MethodInfo . GetCurrentMethod ( ). Név );
var reusablePool = new ReusablePool ();
var thrd1 = új szál ( Futtatás );
var thrd2 = új szál ( Futtatás );
var thisObject1 = reusablePool . GetObject ();
var thisObject2 = reusablePool . GetObject ();
thrd1 . Start ( reusablePool );
thrd2 . Start ( reusablePool );
ViewObject ( thisObject1 );
ViewObject ( thisObject2 );
szál . Alvás ( 2000 );
újrafelhasználható medence . Release ( thisObject1 );
szál . Alvás ( 2000 );
újrafelhasználható medence . Release ( thisObject2 );
Konzol . ReadKey ();
}
private static void Futtatás ( Object obj )
{
Konzol . WriteLine ( "\t" + System . Reflection . MethodInfo . GetCurrentMethod (). Név );
var reusablePool = ( ReusablePool ) obj ;
Konzol . WriteLine ( "\tstart vár" );
var thisObject1 = reusablePool . WaitForObject ();
ViewObject ( thisObject1 );
Konzol . WriteLine ( "\tend wait" );
újrafelhasználható medence . Release ( thisObject1 );
}
private static void ViewObject ( Újrafelhasználható thisObject )
{
foreach ( var obj in thisObject . Objs )
{
Console . Write ( obj . ToString () + @" " );
}
Konzol . writeLine ();
}
}
}
Forrásszöveg VB.NET nyelven
Névtér Digital_Patterns.Creational.Object_Pool.Soft
' Interfész az "Object Pool" sablon használatához <lásd cref="Object_Pool"/>
Public Interface ICreation ( Of T )
' Visszaadja az újonnan létrehozott objektumot
Function Create () As T
End Interface
névtér vége
Forrásszöveg VB.NET nyelven
Névtér Digital_Patterns.Creational.Object_Pool.Soft
'Objektumkészlet-megvalósítás puha hivatkozások használatával
Public Class ObjectPool ( Of T As Class )
'Szinkronizálja az
objektumot Privát szemafor szemaforként
'A gyűjtemény felügyelt objektumokat tartalmaz
Privát készlet ArrayList néven
"Hivatkozás arra az objektumra, amelyre a készlet
Private Creator As ICreation ( Of T ) objektumainak létrehozásának felelőssége át van ruházva
'A jelenleg létező objektumok száma
Private m_instanceCount As Int32
'Az összevont objektumok maximális száma
Privát m_maxInstances As Int32
Az 'Object Pool Creation
' létrehozó az az objektum, amelyre a készlet átruházza a felelősséget az általa kezelt objektumok létrehozásáért
Public Sub New ( ByVal creator As ICreation ( Of T ))
Me . Új ( készítő , Int32 . MaxValue )
End Sub
'Objektumkészlet létrehozása
' creator - Az objektum, amelyre a készlet átruházza a felelősséget az általa kezelt objektumok létrehozásáért.
' maxInstances - Az osztály azon példányainak maximális száma, amelyeket a készlet egyidejűleg engedélyezni fog
Public Sub New ( ByVal creator As ICreation ( Of T ), ByVal maxInstances As Int32 )
me . teremtő = teremtő
Én . m_instanceCount = 0
Me . m_maxInstances = maxInstances
Me . pool = Új ArrayList ()
Me . szemafor = Új szemafor ( 0 , Me . m_maxInstances )
End Sub
'A készletben lévő, újrafelhasználásra váró objektumok számát adja vissza
. A tényleges szám kisebb lehet ennél
az értéknél, mert a visszaadott érték
a készletben lévő lágy hivatkozások száma.
Nyilvános , csak olvasható tulajdonság mérete () Int32 - ként Get SyncLock pool Return pool . Count End SyncLock End Get End Property
'A jelenleg létező
összevont objektumok számát adja vissza. ' Public ReadOnly Property InstanceCount () As Int32
Get
Return m_instanceCount
End Get
End Property
Szerezze be vagy állítsa be a készlet által felügyelt objektumok maximális számát,
amelyet a készlet egyszerre engedélyez.
Public Property MaxInstances ( ) As Int32
Get
Return m_max Instances
End Get
Set ( ByVal érték mint Int32 )
m_maxInstances = érték
End Set
End Tulajdonság
'Egy tárgyat ad vissza a készletből. Egy üres készlet akkor hoz létre
objektumot, ha a készlet által kezelt objektumok száma nem
nagyobb vagy egyenlő, mint az ObjectPool{T}.MaxInstances metódus által visszaadott érték.
'Ha a gyűjtött objektumok száma meghaladja ezt az értéket, akkor ez a
'metódus nullát ad vissza
Public Function GetObject () As T
SyncLock pool
Dim thisObject As T = RemoveObject ()
Ha thisObject IsNot Nothing Akkor ezt az
Objectet adja vissza End If
If InstanceCount < MaxInstances Then
Return CreateObject ()
End If
Return Nothing
End SyncLock
End Function
' Egy objektumot ad vissza a készletből. Egy üres készlet létrehoz egy
"objektumot, ha a gyűjtött objektumok száma
" nem nagyobb vagy egyenlő az ObjectPool{T} által visszaadott értékkel. MaxInstances metódus
" Ha a gyűjtött objektumok száma meghaladja ezt az értéket,
akkor ez a metódus vár. amíg az objektum
nem lesz elérhető újrafelhasználásra.
Nyilvános függvény WaitForObject () As T
SyncLock készlet
Dim thisObject mint T = RemoveObject ()
Ha ez az objektum nem semmi , akkor adja
vissza ezt az objektumot
End If
If InstanceCount < MaxInstances Then
Return CreateObject ()
End If
End SyncLock
szemafor . WaitOne ()
Return WaitForObject (
) Végfüggvény
' Eltávolít egy objektumot a készletgyűjteményből, és visszaadja
Private Function RemoveObject () As T
While készletként . Szám > 0
Dim refThis = DirectCast ( pool ( készlet . Szám - 1 ), Gyenge hivatkozás )
pool . 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 Befejezési függvény
' Hozzon létre egy objektumot, amelyet ez a készlet kezel.
Privát függvény CreateObject () As T
Dim newObject As T = creator . Create ()
m_instanceCount += 1 Új
Object End Function visszaadása
' Felszabadítja az objektumot, és a készletbe helyezi újrafelhasználás céljából Nyilvános alkiadás ( ByVal obj As T ) Ha az obj semmi , akkor dobjon új NullReferenceException () End If SyncLock pool Dim refThis = New WeakReference ( obj ) pool . Adjon hozzá ( refThis ) szemafort . Release () End SyncLock End Sub End Class End névtér
Forrásszöveg VB.NET nyelven
Névtér Digital_Patterns.Creational.Object_Pool.Soft
'### Osztály újrafelhasználható ####
Nyilvános osztály Újrafelhasználható
Privát m_Objs mint objektum ()
Public Sub New ( ByVal ParamArray objs As Object ( ))
Me . Objs = objs
End Sub
Public Property Objs () Objektumként ( ) Get Return m_Objs End Get
Védett halmaz ( ByVal érték mint objektum (
) ) m_Objs = érték
Végkészlet vége Tulajdonság végosztály
'### Class Creator ####
Public Class Creator
valósítja meg az ICreation-t ( újrafelhasználható )
Privát megosztott azonosító , mint Int32 = 0
Nyilvános funkció Create () As Reusable Implements ICreation ( Of Reusable ). Create
iD += 1
Return New Reusable ( iD )
End Function
End Class
„### ReusablePool Class ####
Public Class ReusablePool
örökli az ObjectPool- t ( az újrafelhasználhatóból )
Nyilvános Sub Új ()
MyBase . Új ( Új alkotó (), 2 )
End Sub
End Class
End névtér
Forrásszöveg VB.NET nyelven
Importálás System.Threading
Importálás Digital_Patterns.Creational.Object_Pool.Soft
Névtér Digital_Patterns
Class Program
Megosztott al- fő ()
Konzol . WriteLine ( System . Reflection . MethodInfo . GetCurrentMethod ( ). Név )
Dim reusablePool = New ReusablePool ( )
Dim thrd1 = Új szál ( Futtatás címe ) Dim thrd2 = Új szál ( Futtatás címe ) Dim thisObject1 = reusablePool . GetObject () Dim thisObject2 = reusablePool . GetObject ()
thrd1 . Start ( reusablePool )
thrd2 . Indítás ( reusablePool )
ViewObject ( thisObject1 )
ViewObject ( thisObject2 )
szál . Sleep ( 2000 )
reusablePool . Kiadás ( thisObject1 )
szál . Sleep ( 2000 )
reusablePool . Kiadás ( thisObject2 )
Konzol . ReadKey ()
End Sub
Privát megosztott alfutás ( ByVal obj As [ Object ] ) konzol . _ WriteLine ( vbTab & System . Reflection . MethodInfo . GetCurrentMethod (. Név ) Dim reusablePool = DirectCast ( obj , ReusablePool )
Konzol . WriteLine ( vbTab & "kezdési várakozás" )
Dim thisObject1 = reusablePool . WaitForObject ()
ViewObject ( thisObject1 )
konzol . WriteLine ( vbTab & "end wait" )
reusablePool . Release ( thisObject1 )
End Sub
Privát megosztott alnézeti objektum ( ByVal thisObject újrafelhasználhatóként ) Minden objektumhoz , mint objektum ebben az objektumban . Objs konzol . Write ( obj . ToString ( ) & " " ) Következő konzol . WriteLine () End Sub End Class End névtér
Forrásszöveg Perlben
#!/usr/bin/perl -w
= megjegyzésre
Az ObjectPool modul úgy valósítja meg az "objektumkészlet" programozási mintát, hogy szimulálja
egy íjász viselkedését, akinek korlátozott számú nyila van a tegezében, aminek következtében
rendszeresen fel kell vennie azokat.
A csomag az íjász viselkedését írja le
= vágott
csomag íjász {
használd a Quivert ; # tegez íjász nyilaival
szigorúan használd ;
figyelmeztetések használata ;
konstans használata ARROWS_NUMBER => 5 ; # a nyilak száma a tegezben
használjon állandót SLEEP_TIME => 3 ; # maximális szünet két művelet között (másodpercben)
# -- ** konstruktor ** --
sub new {
my $class = shift ;
my $self = {
tegez => Tegez -> new ( ARROWS_NUMBER ), # "Quiver" osztály objektuma
};
áldja meg $self , $class ;
return $self ;
}
# -- ** felvétel inicializálása ** --
sub shooting_start {
my ( $self ) = ( shift );
while ( 1 ) { # feltételesen végtelen ciklus, amely
$self -> shoot () for ( 0 .. rand ( ARROWS_NUMBER - 1 )); # véletlenszerű számú lövés
$self -> újratöltés () for ( 0 .. rand ( ARROWS_NUMBER - 1 )); # véletlenszerű számú kilőtt nyilak
}
}
# -- ** shot ** --
sub shoot {
my ( $self ) = ( shift );
$self -> { tegez } -> arrow_pull (); # küldje el a nyilat a pokolba
alvás rand ( SLEEP_TIME ); # ... és várj a végtelenségig
}
# -- ** a kilőtt nyíl visszaadása ** --
sub reload {
my ( $self ) = ( shift );
$self -> { tegez } -> arrow_return (); # visszaadja az előzőleg kilőtt nyilat
alvó rand -ot ( SLEEP_TIME ); # és újra várunk
}
}
$íjász = Íjász -> új (); # a bátor íjász elveszi a nyilak tegezét
$íjász -> shooting_start (); # ... és elkezd lőni
= megjegyzésre
A csomag leírja az íjász által használt tegez tulajdonságait (Archer), és amelyben a nyilakat tárolják (Arrow)
= vágott
csomagtegez { _
használja az Arrow ; # egy nyíl a tegezből
használja a "say" funkciót ; szigorúan használd ; figyelmeztetések használata ;
# -- ** konstruktor ** --
sub new {
my ( $osztály , $nyilak_száma ) = ( shift , shift );
my $self = {
nyilak => [] , # nyilak a tegezben (még nem, de hamarosan ott lesz)
};
áldja meg $self , $class ;
$self -> arrows_prepare ( $nyilak_száma ); # nyilak betöltése quiverbe
return $self ;
}
# -- ** nyilak előkészítése a lövöldözéshez ** --
sub arrows_prepare {
my ( $self , $nyilak_száma ) = ( shift , shift );
push @ { $self -> { arrows }}, Arrow -> new ( $_ ) for ( 0 .. $nyilak_száma - 1 ); # tedd a nyilakat a tegezbe
}
# -- ** pull arrow from quiver ** --
sub arrow_pull {
my ( $self ) = ( shift );
foreach ( @ { $self -> { nyilak }}) { # minden nyílnál ellenőrizze, hogy benne van-e a tegezben
if ( $_ -> check_state ()) { # és ha igen, akkor
$_ -> pull (); # vedd ki onnan (és lődd le)
utoljára ; # nem tudunk egyszerre két nyilat kilőni
}
}
}
# -- ** return arrow to quiver ** --
sub arrow_return {
my ( $self ) = ( shift );
foreach ( @ { $self -> { nyilak }}) { # minden nyílnál ellenőrizze, hogy már el lett- e indítva
if ( ! $_ -> check_state ()) { # ha nincs ilyen nyíl a tegezben
$_ -> visszatérés ( ); # menj és vedd fel
utoljára ; # elméletileg egy íjász egyszerre több nyilat is fel tud venni, de a szerző másként gondolja
}
}
}
}
1 ;
= megjegyzésre
A csomag egy íjász tegezében található egyetlen nyíl tulajdonságait írja le (Íjász)
= vágott
csomag Arrow {
használja a "say" funkciót ; szigorúan használd ; figyelmeztetések használata ;
# -- ** konstruktor ** --
sub new {
my $class = shift ;
my $self = {
szám => shift , # arrow number
state => 1 , # arrow state (1 = tegezben, 0 = fekvés lövés után)
};
áldja meg $self , $class ;
return $self ;
}
# -- ** nyíl eltávolítása a tegezből ** --
sub pull {
my ( $self ) = ( shift );
$self -> { állapot } = 0 ; # módosítsa a nyíl állapotát "kibocsátva"-ra,
mondd: "pulled $self->{number}" ; # jelentés arról, hogy a lövés megtörtént
}
# -- ** tedd vissza a nyilat a tegezbe ** --
sub return {
my ( $self ) = ( shift );
$self -> { állapot } = 1 ; # módosítsa a nyíl állapotát "remegett"-re
, mondd : "returned $self->{number}" ; # jelentés, hogy a nyíl visszatért az íjászhoz
}
# -- ** check arrow state ** --
sub check_state {
my ( $self ) = ( shift );
return $self -> { állapot }; # visszaadja a nyíl állapotát (1 = remegett, 0 = elengedett)
}
}
1 ;
Linkek