strategy prototipos prototipo patrones patron ejemplo diseño design-patterns prototype-pattern

design-patterns - patrones - prototipos java



¿Cuál es el punto del patrón de diseño del Prototipo? (6)

El patrón Prototype es un patrón de creación basado en la clonación de un objeto preconfigurado. La idea es elegir un objeto que esté configurado para el caso predeterminado o en el estadio de un caso de uso específico y luego clonar este objeto y configurarlo según sus necesidades exactas.

El patrón es útil para eliminar un montón de código repetitivo, cuando la configuración requerida sería onerosa. Pienso en Prototipos como un objeto preestablecido, donde guarda un montón de estados como un nuevo punto de partida.

Así que estoy aprendiendo sobre los patrones de diseño en la escuela. Hoy me hablaron del patrón de diseño ''Prototipo''.

Debo extrañar algo, porque no veo los beneficios de eso. He visto personas en línea decir que es más rápido que usar new pero esto no tiene sentido; en algún momento, independientemente de cómo se cree el nuevo objeto, la memoria debe asignarse para ello.

¿Este patrón no funciona en los mismos círculos que el problema de "pollo o huevo"? Dado que el patrón Prototype esencialmente solo clona objetos, en algún momento el objeto original debe crearse a sí mismo (es decir, no clonado). ¿Esto significaría que necesito tener una copia existente de cada objeto que quiero clonar que ya esté listo para clonar?

¿Alguien puede explicar cuál es el uso de este patrón?


El patrón de prototipo tiene algunos beneficios, por ejemplo:

  • Elimina la sobrecarga (potencialmente costosa) de inicializar un objeto
  • Simplifica y puede optimizar el caso de uso en el que múltiples objetos del mismo tipo tendrán en su mayoría los mismos datos

Por ejemplo, supongamos que su programa usa objetos que se crean a partir de datos analizados a partir de una información heterogénea recuperada a través de la red. En lugar de recuperar los datos y volver a analizarlos cada vez que se crea un nuevo objeto, el patrón del prototipo se puede usar para simplemente duplicar el objeto original siempre que se necesite uno nuevo.

Además, supongamos que un objeto puede tener datos que consuman grandes cantidades de memoria, como datos que representan imágenes. La memoria se puede reducir mediante el uso de una herencia de estilo de copia sobre escritura, donde se muestran los datos originales, no duplicados, hasta que el código intente cambiar esos datos. Luego, los nuevos datos se enmascararán para hacer referencia a los datos originales.


En comparación con el patrón de fábrica abstracto, al usar el patrón de prototipo, no tiene que tener una gran jerarquía de fábrica, solo una gran jerarquía de productos.


Muchas de las otras respuestas aquí hablan sobre los ahorros de costos de clonar un objeto ya configurado, pero me gustaría expandir el otro "punto" del patrón Prototipo. En algunos idiomas, donde las clases se tratan como objetos de primera clase, puede configurar qué tipo de objeto crea un cliente en tiempo de ejecución simplemente pasándole el nombre de la clase. En lenguajes como C ++, donde las clases no se tratan como objetos de primera clase, el patrón Prototipo le permite lograr el mismo efecto.

Por ejemplo, digamos que tenemos un Chef en un restaurante cuyo trabajo es preparar y servir comidas. Digamos que el Chef está mal pagado y descontento, por lo que hace platos como los siguientes:

class Chef { public: void prepareMeal() const { MozzarellaSticksWithKetchup* appetizer = new MozzarellaSticksWithKetchup(); // do something with appetizer... HockeyPuckHamburgerWithSoggyFries* entree = new HockeyPuckHamburgerWithSoggyFries(); // do something with entree... FreezerBurnedIceCream* dessert = new FreezerBurnedIceCream(); // do something with dessert... } };

Ahora digamos que queremos cambiar al Chef para que sea un ostentoso chef famoso. Esto significa que él / ella tiene new platos diferentes en prepareMeal() . Nos gustaría modificar el método para que los tipos de comidas que el Chef obtenga new ed se puedan especificar como parámetros. En otros idiomas donde las clases son objetos de primera clase, simplemente podemos pasar los nombres de clase como parámetros al método. No podemos hacer esto en C ++, por lo que podemos beneficiarnos del patrón prototipo:

class Appetizer { public: virtual Appetizer* clone() const = 0; // ... }; class Entree { public: virtual Entree* clone() const = 0; // ... }; class Dessert { public: virtual Dessert* clone() const = 0; // ... }; class MozzarellaSticksWithKetchup : public Appetizer { public: virtual Appetizer* clone() const override { return new MozzarellaSticksWithKetchup(*this); } // ... }; class HockeyPuckHamburgerWithSoggyFries : public Entree { public: virtual Entree * clone() const override { return new HockeyPuckHamburgerWithSoggyFries(*this); } // ... }; class FreezerBurnedIceCream : public Dessert { public: virtual Dessert * clone() const override { return new FreezerBurnedIceCream(*this); } // ... }; // ...and so on for any other derived Appetizers, Entrees, and Desserts. class Chef { public: void prepareMeal(Appetizer* appetizer_prototype, Entree* entree_prototype, Dessert* dessert_prototype) const { Appetizer* appetizer = appetizer_prototype->clone(); // do something with appetizer... Entree* entree = entree_prototype->clone(); // do something with entree... Dessert* dessert = dessert_prototype->clone(); // do something with dessert... } };

Tenga en cuenta que un método clone() crea una instancia del tipo derivado, pero devuelve un puntero al tipo padre. Esto significa que podemos cambiar el tipo de objeto que se crea usando un tipo derivado diferente, y el cliente no sabrá la diferencia. Este diseño ahora nos permite configurar un Chef , el cliente de nuestros Prototipos, para hacer diferentes tipos de platos en tiempo de ejecución:

Chef chef; // The same underpaid chef from before: MozzarellaSticksWithKetchup mozzarella_sticks; HockeyPuckHamburgerWithSoggyFries hamburger; FreezerBurnedIceCream ice_cream; chef.prepareMeal(&mozzarella_sticks, &hamburger, &ice_cream); // An ostentatious celebrity chef: IranianBelugaCaviar caviar; LobsterFrittataWithFarmFreshChives lobster; GoldDustedChocolateCupcake cupcake; chef.prepareMeal(&caviar, &lobster, &cupcake);

Puede que se pregunte si, de esta manera, el patrón Prototype le compra lo mismo que el patrón Factory Method, entonces ¿por qué no usar eso? Porque el patrón de Método de fábrica requeriría una jerarquía de clases de creador que refleje la jerarquía de productos que se están creando; es decir, necesitaríamos un MozzarellaSticksWithKetchupCreator con un método make() , un HockeyPuckHamburgerWithSoggyFriesCreator con un método make() , y así sucesivamente. Por lo tanto, podría ver el patrón del Prototipo simplemente como una forma de aliviar la redundancia del código que a menudo introduce el patrón del Método de Fábrica.

Este argumento se extrae de Patrones de diseño: Elementos del software orientado a objetos reutilizables , también conocido como el libro "Banda de cuatro".


Si desea crear un objeto pero no desea realizar el costoso procedimiento de creación de objetos donde se realizan llamadas de red o de base de datos, utilice el patrón de prototipo. Solo crea una copia del objeto y haz los cambios en él.


Si tiene un requerimiento, donde necesita poblar o usar una misma información que contenga objetos repetibles

y

no es posible construir desde un Objeto existente por ejemplo [Objeto de edificio usando el flujo de red] o

construir un Objeto consume mucho tiempo [Construir un Gran Objeto, obteniendo datos de la Base de Datos] y luego usar este patrón de diseño, ya que en este se crea una Copia del Objeto existente, esta copia sería diferente del Objeto Original y podría usarse solo como Original.