Grupo de objetos
La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la
versión revisada el 5 de abril de 2022; las comprobaciones requieren
4 ediciones .
Un conjunto de objetos es un patrón de diseño generador , un conjunto de objetos inicializados y listos para usar. Cuando el sistema necesita un objeto, no lo crea, sino que lo toma del grupo. Cuando ya no se necesita un objeto, no se destruye, sino que se devuelve a la piscina.
Aplicación
La agrupación de objetos se utiliza para mejorar el rendimiento cuando es costoso crear un objeto al comienzo de un trabajo y destruirlo al final. La mejora del rendimiento es especialmente notable cuando los objetos se crean y destruyen con frecuencia, pero solo existe una pequeña cantidad de ellos al mismo tiempo.
Un conjunto de objetos es útil cuando un objeto posee recursos distintos de la memoria, como los sockets de red. O si la colección de objetos ocupa una parte significativa de la memoria de la computadora y se crea mucha " basura ".
Desbordamiento
Si no hay un solo objeto libre en el grupo, es posible una de tres estrategias:
- Ampliación de piscina.
- Negativa a crear un objeto, parada de emergencia.
- En el caso de un sistema multitarea , puede esperar hasta que se libere uno de los objetos.
Ejemplos
- Información sobre archivos abiertos en DOS .
- Información sobre objetos visibles en muchos juegos de computadora ( el motor Doom es un buen ejemplo ). Esta información solo es relevante para un cuadro; después de que se emite el marco, la lista se vacía.
- Un juego de computadora para almacenar todos los objetos en el mapa, en lugar de usar los mecanismos usuales de asignación de memoria, puede crear una matriz de tal tamaño que se sabe que es suficiente para todos los objetos y mantener celdas libres en forma de una lista enlazada. . Este diseño mejora la velocidad, reduce la fragmentación de la memoria y reduce la carga en el recolector de elementos no utilizados (si corresponde).
Trampas
- Después de devolver un objeto, debe volver a un estado adecuado para su uso posterior. Si los objetos, después de regresar a la piscina, se encuentran en un estado incorrecto o indeterminado, dicha construcción se denomina pozo negro de objetos .
- La reutilización de objetos también puede conducir a la fuga de información. Si el objeto contiene datos secretos (por ejemplo, un número de tarjeta de crédito ), después de liberar el objeto, esta información debe sobrescribirse.
- Un grupo de objetos de subprocesos múltiples no es fácil de escribir.
- Para la década de 2020, en los lenguajes recolectados en la basura, la gestión de la memoria está bien optimizada para el retroceso constante de la asignación. Entonces, si el objeto solo ocupa memoria, los manuales de Java no recomiendan usar pools: newuno regular requiere solo diez instrucciones de procesador. Y los recolectores de basura a menudo escanean referencias de objetos, no su memoria, porque cuantos más objetos "vivos" hay en la memoria, menor es el rendimiento de dicho recolector.
Ejemplo de implementación
Código fuente en Python
#codificación: utf-8
"""
Imaginemos una situación en la que tenemos una nave que puede soportar varios disparos.
Crear un objeto Disparo es costoso.
Por lo tanto, los objetos de la familia Disparo se crean una vez.
Y después de la vida útil, el objeto permanece en memoria
"""
class Shot ( objeto ):
"""Una entidad que puede sobrevivir a múltiples golpes"""
def __init__ ( self , curso de la vida = 5 ):
self . toda la vida = toda la vida
def actualizar ( auto ):
auto . vida útil -= 1
devuelve uno mismo . vida > 0
class ObjectPool :
"""Object Pool"""
def __init__ ( self , ** kwargs ):
"""Creando el pool"""
self . _clsname = kwargs [ 'nombre de clase' ]
self . _args = kwargs . obtener ( 'argumentos' , [])
self . _num_objects = max ( kwargs [ 'num' ], 0 )
self . _pred = kwargs [ 'update_func' ]
self . _max_objects = kwargs . obtener ( 'max' , self . _num_objects )
# Crea los objetos
tú mismo . _objs = [ aplicar ( self . _clsname , self . _args )
para x en el rango ( self . _num_objects )]
self . _end = len ( self . _objs )
def _extend_list ( self , args ):
"""Agregar un lugar al grupo"""
self . _objs . agregar ( aplicar ( self . _clsname , args ))
self . _num_objetos += 1
def add ( self , * args ):
"""Agregar un objeto al grupo"""
newend = self . _end + 1
# Si se alcanza el máximo, cuelga
if newend > self . _max_objects :
return Ninguno
# Si se toman todos los lugares, agregue un lugar más
si newend > len ( self . _objs ):
self . _extend_list ( args )
else :
self . _objs [ auto . _fin ] . restablecer ( * argumentos )
auto . _end += 1
volver a sí mismo . _fin - 1
def update ( self , * args ):
"""Actualizar todos los objetos en el grupo"""
self . _end = partición ( self . _pred , self . _objs , 0 , self . _end , args )
return self . _final
def actualizar_objeto ( x ):
"""Actualizar objeto"""
devuelve x . actualizar ()
def partición ( pred , seq , first , last , * args ):
"""Función de ordenación de objetos"""
if first > last :
return 0
for i in range ( first , last ):
if not pred ( seq [ i ]):
break
else :
return last
para j en el rango ( i + 1 , último ):
si pred ( seq [ j ]):
seq [ i ], seq [ j ] = seq [ j ], seq [ i ]
i += 1
return i
# Actualmente usando el pool
shots = ObjectPool ( classname = Shot , update_func = update_object , num = 5 )
durante los disparos . actualizar ():
pasar
imprimir "¡Listo!"
Texto fuente en C++
#incluir <vector>
objeto de clase
{
// ...
};
clase ObjectPool
{
privado :
struct PoolRecord
{
objeto * instancia ;
bool en_uso ;
};
std :: vector < PoolRecord > m_pool ;
público :
Objeto * crearNuevoObjeto ()
{
for ( tamaño_t i = 0 ; i < m_pool . tamaño (); ++ i )
{
if ( ! m_pool [ i ]. en_uso )
{
m_piscina [ yo ]. en_uso = verdadero ; // transferir el objeto a la lista de usados return m_pool [ i ]. instancia ;
}
}
// si no encontramos un objeto libre, expanda el
registro PoolRecord del grupo ;
grabar _ instancia = nuevo objeto ;
grabar _ en_uso = verdadero ;
m_piscina . push_back ( registro );
registro de retorno . instancia ;
}
void deleteObject ( Objeto * objeto )
{
// en realidad, no borramos, solo marcamos que el objeto está libre
para ( size_t i = 0 ; i < m_pool . size (); ++ i )
{
if ( m_pool [ i ]. instancia == objeto )
{
m_piscina [ yo ]. en_uso = falso ;
romper ;
}
}
}
grupo de objetos virtual ~ ()
{
// ahora "realmente" eliminamos objetos
para ( size_t i = 0 ; i < m_pool . size (); ++ i )
eliminar m_pool [ i ]. instancia ;
}
};
int principal ()
{
Grupo de objetos ;
para ( tamaño_t i = 0 ; i < 1000 ; ++ i )
{
Objeto * objeto = piscina . crearNuevoObjeto ();
// ...
piscina . eliminarObjeto ( objeto );
}
devolver 0 ;
}
Las plantillas y la seguridad de subprocesos se han eliminado del ejemplo por simplicidad . Si necesita usar el grupo en varios subprocesos, debe proteger el cuerpo de los métodos createNewObject y deleteObject de la ejecución simultánea por parte de algún objeto de sincronización adecuado, como una sección crítica o un mutex .
Ejemplo en C#
Texto fuente en C#
namespace Digital_Patterns.Creational.Object_Pool.Soft
{
/// <summary>
/// Interfaz para usar el patrón "Object Pool" <see cref="Object_Pool"/>
/// </summary>
/// <typeparam name= " T"></typeparam>
public interface ICreation < T >
{
/// <summary>
/// Devuelve el objeto recién creado
/// </summary>
/// <returns></returns>
T Create () ;
}
}
Texto fuente en C#
utilizando el sistema ;
utilizando System.Collections ;
utilizando System.Threading ;
espacio de nombres Digital_Patterns.Creational.Object_Pool.Soft
{
/// <summary>
/// Implementación de un grupo de objetos usando referencias flexibles
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObjectPool < T > donde T : class
{
/// <summary>
/// Objeto de sincronización
/// </summary>
private Semaphore semaphore ;
/// <summary>
/// La colección contiene objetos administrados
/// </summary>
private ArrayList pool ;
/// <summary>
/// Referencia al objeto al que se delega la responsabilidad
/// de crear los objetos del pool
/// </summary>
private ICreation < T > created ;
/// <summary>
/// El número de objetos que existen actualmente
/// </summary>
private Int32 instanceCount ;
/// <summary>
/// Número máximo de objetos administrados por el grupo
/// </summary>
private Int32 maxInstances ;
/// <summary>
/// Creación de un grupo de objetos
/// </summary>
/// <param name="creator">El objeto en el que el grupo delegará la responsabilidad
/// de crear los objetos que administra< /param>
ObjectPool público ( ICreation < T > creador ) : este ( creador , Int32 . MaxValue ) { }
/// <summary>
/// Creación de un grupo de objetos
/// </summary>
/// <param name="creator">El objeto en el que el grupo delegará la responsabilidad
/// de crear los objetos que administra< /param>
/ // <param name="maxInstances">El número máximo de instancias de clase
/// que el grupo permite que existan al mismo tiempo
/// </param>
public ObjectPool ( ICreation < T > creador , Int32 maxInstances )
{
esto . creador = creador ;
esto _ recuento de instancias = 0 ;
esto _ maxInstances = maxInstances ;
esto _ grupo = nueva lista de arreglos ();
esto _ semáforo = nuevo Semáforo ( 0 , this . maxInstances );
}
/// <summary>
/// Devuelve el número de objetos en el grupo que esperan ser
/// reutilizados. El número real
/// puede ser menor que este valor, porque
/// el valor devuelto es el número de referencias flexibles en el grupo.
/// </summary>
public Int32 Size
{
get
{
lock ( pool )
{
return pool . contar ;
}
}
}
/// <summary>
/// Devuelve el número de objetos agrupados
/// que existen actualmente
/// </summary>
public Int32 InstanceCount { get { return instanceCount ; } }
/// <summary>
/// Obtenga o establezca el número máximo de
/// objetos administrados que el grupo permitirá que existan al mismo tiempo.
/// </summary>
public Int32 MaxInstances
{
get { return maxInstances ; }
establecer { maxInstances = valor ; }
}
/// <summary>
/// Devuelve un objeto del grupo. Con un grupo vacío,
se creará un /// objeto si el número de objetos
/// administrados por el grupo no es mayor o igual que el valor
/// devuelto por el <see cref="ObjectPool{T}. MaxInstances"/> método. Si la cantidad de objetos /// administrados por el grupo
excede este valor, entonces este método devuelve un valor nulo
/// </summary>
/// <returns></returns>
public T GetObject ()
{
lock ( pool )
{
T esteObjeto = QuitarObjeto ( );
if ( esteObjeto != nulo )
devuelve esteObjeto ;
if ( InstanceCount < MaxInstances )
devuelve CreateObject ();
devolver nulo ;
}
}
/// <summary>
/// Devuelve un objeto del grupo. Con un grupo vacío,
se creará un /// objeto si el número de objetos
/// administrados por el grupo no es mayor o igual que el valor
/// devuelto por el <see cref="ObjectPool{T}. MaxInstances"/> método. Si el número de objetos /// administrados por el grupo
excede este valor, entonces este método esperará hasta que
/// algún objeto esté disponible para
/// reutilizarlo.
/// </summary>
/// <devoluciones></devoluciones>
public T WaitForObject ()
{
lock ( pool )
{
T thisObject = RemoveObject ();
if ( esteObjeto != nulo )
devuelve esteObjeto ;
if ( InstanceCount < MaxInstances )
devuelve CreateObject ();
}
semáforo . esperar uno ();
devuelve WaitForObject ();
}
/// <summary>
/// Elimina un objeto de la colección del pool y lo devuelve
/// </summary>
/// <returns></returns>
private T RemoveObject ()
{
while ( pool . Count > 0 )
{
var refThis = ( Referencia débil ) grupo [ grupo . Cuenta - 1 ];
piscina _ RemoveAt ( pool . Count - 1 );
var esteObjeto = ( T ) refEste . objetivo ;
if ( esteObjeto != nulo )
devuelve esteObjeto ;
recuento de instancias --;
}
devuelve nulo ;
}
/// <summary>
/// Crea un objeto administrado por este grupo
/// </summary>
/// <returns></returns>
private T CreateObject ()
{
T newObject = creador . crear ();
recuento de instancias ++;
volver nuevoObjeto ;
}
/// <summary>
/// Libera el objeto, colocándolo en el pool para
/// reutilizarlo
/// </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 );
piscina _ Agregar ( refEsto );
semáforo _ liberar ();
}
}
}
}
Texto fuente en C#
espacio de nombres Digital_Patterns.Creational.Object_Pool.Soft
{
public class Reusable
{
public Object [] Objs { get ; conjunto protegido ; }
public Reutilizable ( params Object [] objs )
{
this . objs = objs ;
}
}
Creador de clase pública : ICreation < Reusable > { private static Int32 iD = 0 ;
Public Reutilizable Create ()
{
++ iD ;
devolver nuevo Reutilizable ( iD );
}
}
public class ReusablePool : ObjectPool < Reusable >
{
public ReusablePool ()
: base ( new Creator (), 2 )
{
}
}
}
Texto fuente en C#
utilizando el sistema ;
utilizando System.Threading ;
utilizando Digital_Patterns.Creational.Object_Pool.Soft ;
espacio de nombres Digital_Patterns
{
class Program
{
static void Main ( cadena [] args )
{
Console . WriteLine ( System . Reflection . MethodInfo . GetCurrentMethod (). Name );
var reusablePool = new ReusablePool ();
var thrd1 = hilo nuevo ( Ejecutar ); var thrd2 = hilo nuevo ( Ejecutar ); var thisObject1 = grupo reutilizable . ObtenerObjeto (); var thisObject2 = grupo reutilizable . ObtenerObjeto (); thrd1 . Inicio ( reutilizablePool ); thrd2 . Inicio ( reutilizablePool ); VerObjeto ( esteObjeto1 ); VerObjeto ( esteObjeto2 ); hilo _ Sueño ( 2000 ); Piscina reutilizable . Liberar ( esteObjeto1 ); hilo _ Sueño ( 2000 ); Piscina reutilizable . Liberar ( esteObjeto2 );
consola _ Clave de lectura ();
}
vacío estático privado Ejecutar ( Objeto obj ) { Consola . WriteLine ( "\t" + System . Reflection . MethodInfo . GetCurrentMethod (). Name ); var piscina reutilizable = ( piscina reutilizable ) obj ; consola _ WriteLine ( "\tstart esperar" ); var thisObject1 = grupo reutilizable . EsperarObjeto (); VerObjeto ( esteObjeto1 ); consola _ WriteLine ( "\tend espera" ); Piscina reutilizable . Liberar ( esteObjeto1 ); }
privado estático vacío ViewObject ( Reutilizable thisObject )
{
foreach ( var obj in thisObject . Objs )
{
Console . Escribir ( obj . ToString () + @" " );
}
Consola . escribirLinea ();
}
}
}
Texto fuente en lenguaje VB.NET
Espacio de nombres Digital_Patterns.Creational.Object_Pool.Soft
' Interfaz para usar la plantilla "Object Pool" <see cref="Object_Pool"/>
Public Interface ICreation ( Of T )
' Devuelve el objeto recién creado
Función Create () As T
End Interface
espacio de nombres final
Texto fuente en lenguaje VB.NET
Espacio de nombres Digital_Patterns.Creational.Object_Pool.Soft
'Implementación del grupo de objetos usando referencias suaves
Public Class ObjectPool ( Of T As Class )
'Sincronizar objeto
Semáforo privado Como semáforo
'La colección contiene objetos administrados
Grupo privado como ArrayList
'Referencia al objeto en el que se delega la responsabilidad de crear los objetos del pool
Private Creator As ICreation ( Of T )
'Número de objetos existentes actualmente
Privado m_instanceCount As Int32
'Número máximo de objetos agrupados
Private m_maxInstances As Int32
El creador de ' Creación de grupo de objetos
' es el objeto en el que el grupo delegará la responsabilidad de crear los objetos que administra
Public Sub New ( Creador de ByVal As ICreation ( Of T )) Me . Nuevo ( creador , Int32 . MaxValue ) End Sub
'Creación de un conjunto de objetos
' creador: el objeto al que el conjunto delegará la responsabilidad de crear los objetos que administra
' maxInstances: la cantidad máxima de instancias de la clase que el conjunto permitirá que existan al mismo tiempo
Public Sub New ( ByVal creador As ICreation ( Of T ), ByVal maxInstances As Int32 )
me . creador = creador
Yo . m_instanceCount = 0
Yo . m_maxInstances = maxInstances
Yo . pool = New ArrayList ()
Me . semáforo = Nuevo semáforo ( 0 , Me . m_maxInstances )
End Sub
'Devuelve el número de objetos en el grupo que esperan ser reutilizados
. El número real puede ser menor que
este valor, porque el valor devuelto
es el número de referencias blandas en el grupo.
Tamaño de propiedad de solo lectura pública () como Int32 Obtener grupo de SyncLock Grupo de retorno . Contar Fin SyncLock Fin Obtener Fin Propiedad
'Devuelve el número de objetos agrupados que
existen actualmente'
Public ReadOnly Property InstanceCount () As Int32
Get
Return m_instanceCount
End Obtener
End Property
Obtenga o establezca la cantidad máxima de
objetos administrados por el grupo que el grupo permitirá que existan en cualquier momento.
Public Property MaxInstances () As Int32
Obtener
Retorno m_maxInstances
End Get
Set ( ByVal value As Int32 )
m_maxInstances = valor
End Set
End Property
'Devuelve un objeto de la piscina. Un grupo vacío creará un
'objeto si la cantidad de objetos administrados por el grupo no es
mayor o igual que el valor devuelto por el método ObjectPool{T}.MaxInstances.
'Si la cantidad de objetos agrupados excede este valor, entonces este
'método devuelve nulo
Public Function GetObject () As T
SyncLock pool
Dim thisObject As T = RemoveObject ()
If thisObject IsNot Nothing Then
Return thisObject
End If
Si InstanceCount < MaxInstances Entonces
devuelve CreateObject ()
End If
No devuelve nada
Finaliza la función de finalización de SyncLock
' Devuelve un objeto del grupo. Un grupo vacío creará un
' objeto si el número de objetos agrupados
' no es mayor o igual que el valor devuelto por el método ObjectPool{T}.MaxInstances
' Si el número de objetos agrupados excede este valor,
' este método esperará hasta que el objeto
' no esté disponible para su reutilización.
Función pública WaitForObject () As T SyncLock pool Dim thisObject As T = RemoveObject () If thisObject IsNot Nothing Then Return thisObject End If
If InstanceCount < MaxInstances Then
Return CreateObject ()
End If
End SyncLock
semaphore . WaitOne ()
Retornar WaitForObject ()
Fin Función
' Elimina un objeto de la colección del grupo y lo devuelve
Private Function RemoveObject () As T
While pool . Count > 0
Dim refThis = DirectCast ( pool ( pool . Count - 1 ), WeakReference )
pool . RemoveAt ( pool . Count - 1 )
Dim thisObject = DirectCast ( refThis . Target , T )
Si thisObject IsNot Nothing Entonces
devuelve thisObject
End If
m_instanceCount -= 1
End While
Return Nothing
End Function
' Crear un objeto administrado por este grupo
Función privada CreateObject () As T Dim newObject As T = creador . Create () m_instanceCount += 1 Retorna newObject End Function
' Libera el objeto, colocándolo en el grupo para su reutilización
Public Sub Release ( ByVal obj As T )
If obj Is Nothing Then
Throw New NullReferenceException ()
End If
SyncLock pool
Dim refThis = New WeakReference ( obj )
pool . Añadir ( refThis )
semáforo . Release ()
End SyncLock
End Sub
End Class
End Namespace
Texto fuente en lenguaje VB.NET
Espacio de nombres Digital_Patterns.Creational.Object_Pool.Soft
'### Clase reutilizable ####
Clase pública reutilizable
Privado m_Objs como objeto ()
Public Sub New ( ByVal ParamArray objs As Object ())
Me . Objs = objs
End Sub
Public Property Objs () As Object ()
Get
Return m_Objs
End Get
Conjunto protegido ( ByVal value As Object ())
m_Objs = value
End Set
End Property
End Class
'### Class Creator ####
Public Class Creator
implementa ICreation ( of Reusable )
ID compartida privada como Int32 = 0
La función pública Create () As Reusable implementa ICreation ( Of Reusable ). Crear
iD += 1
Devolver nuevo reutilizable ( iD )
Finalizar función
Finalizar clase
'### ReusablePool Class ####
Clase pública ReusablePool hereda ObjectPool ( de reutilizable )
Public Sub Nuevo ()
MyBase . Nuevo ( Nuevo creador (), 2 )
End Sub
End Class
End Namespace
Texto fuente en lenguaje VB.NET
Importaciones System.Threading
Importaciones Digital_Patterns.Creational.Object_Pool.Soft
Programa de clase de patrones digitales de espacio de
nombres
Consola principal secundaria compartida () . WriteLine ( System . Reflection . MethodInfo . GetCurrentMethod ( ). Name ) Dim reusablePool = New ReusablePool ()
Dim thrd1 = Nuevo hilo ( AddressOf Run )
Dim thrd2 = Nuevo hilo ( AddressOf Run )
Dim thisObject1 = reusablePool . GetObject ()
Dim thisObject2 = grupo reutilizable . ObtenerObjeto ()
thrd1 . Inicie ( grupo reutilizable )
thrd2 . Inicio ( reutilizablePool )
VerObjeto ( esteObjeto1 )
VerObjeto ( esteObjeto2 )
hilo _ Sleep ( 2000 )
piscina reutilizable . Liberar ( esteObjeto1 )
hilo _ Sleep ( 2000 )
piscina reutilizable . Liberar ( esteObjeto2 )
consola _ Tecla de lectura ()
End Sub
Subejecución compartida privada ( ByVal obj As [ Objeto ] ) Consola . _ WriteLine ( vbTab & System . Reflection . MethodInfo . GetCurrentMethod (. Name ) Dim reusablePool = DirectCast ( obj , ReusablePool )
consola _ WriteLine ( vbTab & "start wait" )
Dim thisObject1 = reusablePool . EsperarObjeto ()
ViewObject ( esteObjeto1 )
Consola . WriteLine ( vbTab & "end wait" )
reusablePool . Liberar ( thisObject1 )
End Sub
Sub ViewObject privado compartido ( ByVal thisObject como reutilizable ) para cada obj como objeto en thisObject . Consola Objs . Escribir ( obj . ToString ( ) & " " ) Consola siguiente . WriteLine () End Sub End Class End Espacio de nombres
Texto fuente en Perl
#!/usr/bin/perl-w
= para comentar
El módulo ObjectPool implementa el patrón de programación "object pool" simulando
el comportamiento de un arquero que tiene un número limitado de flechas en su carcaj, por
lo que debe recogerlas periódicamente.
El paquete describe el comportamiento del arquero.
=cortar
paquete arquero {
usar carcaj ; # carcaj con flechas de arquero
uso estricto ;
advertencias de uso ;
use constante FLECHAS_NUMERO => 5 ; # número de flechas en el carcaj
use constante SLEEP_TIME => 3 ; # descanso máximo entre dos acciones (en segundos)
# -- ** constructor ** --
sub new {
mi $clase = shift ;
my $self = {
carcaj => Carcaj -> nuevo ( FLECHAS_NUMERO ), # objeto de la clase "Carcaj"
};
bendícete $a ti mismo , $clase ;
devolver $auto ;
}
# -- ** inicialización de disparo ** --
sub shooting_start {
my ( $self ) = ( shift );
while ( 1 ) { # ciclo condicionalmente infinito que dispara
$self -> disparar () for ( 0 .. rand ( NÚMERO_FLECHAS - 1 )); # número aleatorio de disparos
$self -> reload () for ( 0 .. rand ( ARROWS_NUMBER - 1 )); # número aleatorio de devoluciones de flechas disparadas
}
}
# -- ** tiro ** --
sub tiro {
my ( $self ) = ( shift );
$self -> { carcaj } -> arrow_pull (); # enviar la flecha al infierno
dormir rand ( SLEEP_TIME ); # ... y espera indefinidamente
}
# -- ** devuelve la flecha disparada ** --
sub reload {
my ( $self ) = ( shift );
$self -> { carcaj } -> arrow_return (); # devuelve la flecha disparada anteriormente
sleep rand ( SLEEP_TIME ); # y otra vez estamos esperando
}
}
$arquero = Arquero -> nuevo (); # el valiente arquero toma su carcaj de flechas
$arquero -> tiro_inicio (); # ... y comienza a disparar
= para comentar
El paquete describe las propiedades del carcaj utilizado por el arquero (Arquero) y en el que se almacenan las flechas (Flecha)
=cortar
carcaj de paquete {
usa la flecha ; # una flecha del carcaj
usar la función "decir" ;
uso estricto ;
advertencias de uso ;
# -- ** constructor ** --
sub new {
my ( $class , $arrows_number ) = ( shift , shift );
my $self = {
arrows => [] , # arrows in quiver (todavía no, pero estará allí pronto)
};
bendícete $a ti mismo , $clase ;
$self -> arrows_prepare ( $arrows_number ); # cargar flechas en el carcaj
return $self ;
}
# -- ** preparar flechas para disparar ** --
sub arrows_prepare {
my ( $self , $arrows_number ) = ( shift , shift );
push @ { $self -> { arrows }}, Arrow -> new ( $_ ) for ( 0 .. $arrows_number - 1 ); # pon las flechas en el carcaj
}
# -- ** tirar de la flecha del carcaj ** --
sub arrow_pull {
my ( $self ) = ( shift );
foreach ( @ { $self -> { arrows }}) { # para cada flecha, verifique si está en el carcaj
if ( $_ -> check_state ()) { # y si es así
$_ -> pull (); # sacarlo de allí (y disparar)
último ; # no podemos disparar dos flechas al mismo tiempo
}
}
}
# -- ** devuelve la flecha al carcaj ** --
sub arrow_return {
my ( $self ) = ( shift );
foreach ( @ { $self -> { arrows }}) { # para cada flecha, verifique si ya se ha disparado
if ( ! $_ -> check_state ()) { # si no hay tal flecha en el carcaj
$_ -> retorno ( ); # ve y recógelo el
último ; # en teoría, un arquero puede recoger más de una flecha a la vez, pero el autor piensa lo contrario
}
}
}
}
1 ;
= para comentar
El paquete describe las propiedades de una sola flecha que se encuentra en el carcaj de un arquero (Arquero)
=cortar
flecha del paquete {
usar la función "decir" ;
uso estricto ;
advertencias de uso ;
# -- ** constructor ** --
sub new {
mi $clase = shift ;
my $self = {
number => shift , # arrow number
state => 1 , # arrow state (1 = en carcaj, 0 = tirado después del disparo)
};
bendícete $a ti mismo , $clase ;
devolver $auto ;
}
# -- ** quitar la flecha del carcaj ** --
sub pull {
my ( $self ) = ( shift );
$self -> { estado } = 0 ; # cambiar el estado de la flecha a "liberado"
decir "tirado $self->{number}" ; # informe de que se produjo el disparo
}
# -- ** vuelve a colocar la flecha en el carcaj ** --
sub return {
my ( $self ) = ( shift );
$self -> { estado } = 1 ; # cambia el estado de la flecha a "tembló"
dice "devolvió $self->{number}" ; # informar que la flecha ha regresado al arquero
}
# -- ** verificar el estado de la flecha ** --
sub check_state {
my ( $self ) = ( shift );
return $self -> { estado }; # devuelve el estado de la flecha (1 = tembló, 0 = soltó)
}
}
1 ;
Enlaces