Método de prototipo: patrones de diseño de Python

Prototype Method es un patrón de diseño creacional que tiene como objetivo reducir el número de clases utilizadas para una aplicación. Le permite copiar objetos existentes independientemente de la implementación concreta de sus clases. Generalmente, aquí el objeto se crea copiando una instancia prototípica durante el tiempo de ejecución. 
Se recomienda encarecidamente utilizar el método Prototype cuando la creación del objeto es una tarea costosa en términos de tiempo y uso de recursos y ya existe un objeto similar. Este método proporciona una forma de copiar el objeto original y luego modificarlo según nuestras necesidades.

Problemas a los que nos enfrentamos sin el método prototipo

Supongamos que tenemos una clase Shape que produce diferentes formas como un círculo, un rectángulo, un cuadrado, etc. y ya tenemos un objeto de ella. Ahora queremos crear la copia exacta de este objeto. ¿Cómo irá un desarrollador ordinario?  
Él/Ella creará un nuevo objeto de la misma clase y aplicará todas las funcionalidades de los objetos originales y copiará sus valores. Pero no podemos copiar todos y cada uno de los campos del objeto original, ya que algunos pueden ser privados y estar protegidos y no están disponibles desde el exterior del propio objeto. 
¡Aquí no se acaban los problemas! también se vuelve dependiente del código de otra clase, lo que ciertamente no es una buena práctica en el desarrollo de software.

Para una mejor comprensión, entendamos el ejemplo de Courses At GeeksforGeeks que brinda cursos como SDE, DSA, STL, etc. Crear objetos para cursos similares, una y otra vez, no es una buena tarea para utilizar los recursos de una mejor manera.
 

problem-builder-method

método-constructor-de-problemas

Nota: el siguiente código está escrito sin utilizar el método de prototipo

Python3

# concrete course
class DSA():
    """Class for Data Structures and Algorithms"""
 
    def Type(self):
        return "Data Structures and Algorithms"
 
    def __str__(self):
        return "DSA"
 
 
# concrete course
class SDE():
    """Class for Software development Engineer"""
 
    def Type(self):
        return "Software Development Engineer"
 
    def __str__(self):
        return "SDE"
 
 
# concrete course
class STL():
    """class for Standard Template Library of C++"""
 
    def Type(self):
        return "Standard Template Library"
 
    def __str__(self):
        return "STL"
 
 
# main method
if __name__ == "__main__":
    sde = SDE()  # object for SDE
    dsa = DSA()  # object for DSA
    stl = STL()  # object for STL
 
    print(f'Name of Course: {sde} and its type: {sde.Type()}')
    print(f'Name of Course: {stl} and its type: {stl.Type()}')
    print(f'Name of Course: {dsa} and its type: {dsa.Type()}')

Solución por método de prototipo:

Para hacer frente a tales problemas, utilizamos el método Prototipo. Crearíamos clases separadas para Courses_At_GFG y Course_At_GFG_Cache que nos ayudarán a crear la copia exacta del objeto ya existente con las mismas propiedades de campo. Este método delega el proceso de clonación a los objetos reales que se están clonando. Aquí declaramos una interfaz o clase común que admite la clonación de objetos, lo que nos permite clonar el objeto sin acoplar nuestro código a la clase de ese método. 
Un objeto que admite la clonación se denomina Prototipo

Python3

# import the required modules
 
from abc import ABCMeta, abstractmethod
import copy
 
 
# class - Courses at GeeksforGeeks
class Courses_At_GFG(metaclass = ABCMeta):
     
    # constructor
    def __init__(self):
        self.id = None
        self.type = None
 
    @abstractmethod
    def course(self):
        pass
 
    def get_type(self):
        return self.type
 
    def get_id(self):
        return self.id
 
    def set_id(self, sid):
        self.id = sid
 
    def clone(self):
        return copy.copy(self)
 
# class - DSA course
class DSA(Courses_At_GFG):
    def __init__(self):
        super().__init__()
        self.type = "Data Structures and Algorithms"
 
    def course(self):
        print("Inside DSA::course() method")
 
# class - SDE Course
class SDE(Courses_At_GFG):
    def __init__(self):
        super().__init__()
        self.type = "Software Development Engineer"
 
    def course(self):
        print("Inside SDE::course() method.")
 
# class - STL Course
class STL(Courses_At_GFG):
    def __init__(self):
        super().__init__()
        self.type = "Standard Template Library"
 
    def course(self):
        print("Inside STL::course() method.")
 
# class - Courses At GeeksforGeeks Cache
class Courses_At_GFG_Cache:
     
    # cache to store useful information
    cache = {}
 
    @staticmethod
    def get_course(sid):
        COURSE = Courses_At_GFG_Cache.cache.get(sid, None)
        return COURSE.clone()
 
    @staticmethod
    def load():
        sde = SDE()
        sde.set_id("1")
        Courses_At_GFG_Cache.cache[sde.get_id()] = sde
 
        dsa = DSA()
        dsa.set_id("2")
        Courses_At_GFG_Cache.cache[dsa.get_id()] = dsa
 
        stl = STL()
        stl.set_id("3")
        Courses_At_GFG_Cache.cache[stl.get_id()] = stl
 
# main function
if __name__ == '__main__':
    Courses_At_GFG_Cache.load()
 
    sde = Courses_At_GFG_Cache.get_course("1")
    print(sde.get_type())
 
    dsa = Courses_At_GFG_Cache.get_course("2")
    print(dsa.get_type())
 
    stl = Courses_At_GFG_Cache.get_course("3")
    print(stl.get_type())

Diagrama UML del patrón de diseño de prototipo

prototype-method-uml-diagram

Prototipo-Método – UML-Diagrama

Ventajas

  1. Menos número de subclases: todos los demás patrones de diseño creativo proporcionan muchas subclases nuevas que definitivamente no son fáciles de manejar cuando estamos trabajando en un proyecto grande. Pero usando Prototype Design Pattern, nos deshacemos de esto.
  2. Proporciona valores variables a nuevos objetos: todos los sistemas altamente dinámicos le permiten definir un nuevo comportamiento a través de la composición de objetos especificando valores para las variables de un objeto y no definiendo nuevas clases.
  3. Proporciona una estructura variable a los objetos nuevos: por lo general, todas las aplicaciones crean objetos a partir de partes y subpartes. Por conveniencia, tales aplicaciones a menudo le permiten instanciar estructuras complejas definidas por el usuario para usar un subcircuito específico una y otra vez.

Desventajas

  1. Abstracción: ayuda a lograr la abstracción al ocultar los detalles de implementación concretos de la clase.
  2. Desperdicio de recursos en el nivel inferior: podría demostrarse que es un exceso de recursos para un proyecto que utiliza muy pocos objetos.

Aplicabilidad

  1. Independencia de la clase concreta: el método de prototipo proporciona la forma de implementar los nuevos objetos sin depender de la implementación concreta de la clase.
  2. Problemas recurrentes: el método de prototipo también se utiliza para resolver los problemas recurrentes y complejos del desarrollo de software.

Lectura adicional: patrón de diseño de prototipo en Java
 

Publicación traducida automáticamente

Artículo escrito por chaudhary_19 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *