Patrones de diseño intuitivo: Cómo reconocer los patrones que siempre ha utilizado (Parte 1: Patrones de creación)
El patrón de diseño Prototipo crea nuevos objetos clonando una instancia existente, en lugar de instanciar una clase. Funciona así: usted inicializa un objeto y establece sus propiedades. Cuando necesite un objeto similar, simplemente crea una copia o “prototipo” del original. Este método resulta ventajoso en situaciones en las que la creación de objetos requiere muchos recursos o depende de configuraciones de estado complejas. Así, en lugar de pasar cada vez por el laborioso proceso de instanciación, usted crea un objeto una vez y luego hace copias cuando las necesita, lo que favorece la eficacia y la facilidad de uso.
Qué buscar en su código
- El proceso de creación tiene mucha sobrecarga pero se necesitan muchas instancias de esta clase.
- Ya tiene un objeto y necesita casi el mismo objeto, pero con sólo un par de cosas cambiadas.
- Ya tiene un objeto con la mayor parte del estado necesario, por lo que puede simplemente clonarlo en lugar de tener que pasar por toda la dificultad de crear un nuevo objeto.
- Si un sistema utiliza un gran número de subclases que sólo difieren en su estado, podría emplearse el patrón Prototipo para reducir el número de clases creadas.
Ejemplo básico
import copyclass Prototype:
def __init__(self):
self._objects = {}
def register_object(self, name, obj):
"""Register an object."""
self._objects[name] = obj
def unregister_object(self, name):
"""Unregister an object."""
del self._objects[name]
def clone(self, name, **attr):
"""Clone a registered object and update its attributes."""
obj = copy.deepcopy(self._objects.get(name))
obj.__dict__.update(attr)
return obj
class Car:
def __init__(self):
self.name = "Skylark"
self.color = "Red"
self.options = "Ex"
car = Car()
prototype = Prototype()
prototype.register_object('skylark', car)
car1 = prototype.clone('skylark')
print(car1)
car2 = prototype.clone('skylark', color="Green")
print(car2.color) # Output: Green
Aplicaciones concretas
El patrón Prototipo es especialmente útil cuando el coste de crear un objeto es elevado en términos de recursos o tiempo, o cuando el sistema necesita ser independiente de cómo se crean, componen y representan sus productos.
- Desarrollo de juegos: En el desarrollo de juegos, objetos como enemigos, árboles o baldosas de terreno pueden ser clones de un prototipo, para reducir el uso de memoria. Esto es crucial cuando el juego necesita instanciar cientos o miles de objetos similares.
- Operaciones de base de datos: Cuando se trate de operaciones pesadas con la base de datos, puede utilizar el patrón Prototipo para clonar el modelo de datos de la consulta en lugar de realizar una nueva llamada a la base de datos.
- Entorno multihilo: En un entorno multihilo, los prototipos pueden ser útiles para mantener el estado de los objetos, donde cada hilo puede tener una instancia separada del objeto clonado desde el prototipo, evitando conflictos de modificación concurrentes.
El patrón Prototipo debe tenerse en cuenta cuando la creación de un objeto implique más complejidad que la simple instanciación de una clase, como en el caso de operaciones con bases de datos, peticiones de red o tareas de cálculo elevadas. Además, cuando los objetos de una clase pueden tener sólo unos pocos estados diferentes, es ventajoso instalar un número correspondiente de prototipos y clonarlos en lugar de instanciar la clase manualmente cada vez.
Conclusión
Al concluir esta exploración de los patrones de diseño creacionales, recuerde que no son sólo herramientas, sino que forman parte de un lenguaje para articular diseños de software complejos. Llegar a comprender estos patrones fundacionales – el Singleton, el Constructor, el Prototipo, la Fábrica y la Fábrica Abstracta – es el primer paso para adquirir este lenguaje. Gracias por su paciencia y compromiso.
Si desea conocer el resto de patrones de diseño estructurales y de comportamiento, permanezca atento a mis próximos artículos.