Wat is het nut van het prototype-ontwerppatroon?

Dus ik leer over ontwerppatronen op school. Vandaag kreeg ik te horen over het ‘Prototype’ ontwerppatroon.

Ik moet iets missen, want ik zie er de voordelen niet van in. Ik heb mensen online zien zeggen dat het sneller is dan het gebruik van new, maar dit slaat nergens op; op een gegeven moment, ongeacht hoe het nieuwe object is gemaakt, moet er geheugen voor worden toegewezen.

Loopt dit patroon niet in dezelfde cirkels als het ‘kip of ei’-probleem? Aangezien het prototypepatroon in wezen gewoon objecten klonen is, moet het originele object op een gegeven moment zelf worden gemaakt (d.w.z. niet gekloond). Dit zou betekenen dat ik een bestaande kopie van elk object dat ik wil klonen al gereed moet hebben om te klonen?

Kan iemand uitleggen wat het nut van dit patroon is?


Antwoord 1, autoriteit 100%

Het prototypepatroon heeft enkele voordelen, bijvoorbeeld:

  • Het elimineert de (potentieel dure) overhead van het initialiseren van een object
  • Het vereenvoudigt en kan het gebruik optimaliseren waarbij meerdere objecten van hetzelfde type meestal dezelfde gegevens hebben

Stel bijvoorbeeld dat uw programma objecten gebruikt die zijn gemaakt op basis van gegevens die zijn geparseerd op basis van meestal onveranderlijke informatie die via het netwerk is opgehaald. In plaats van de gegevens op te halen en elke keer dat een nieuw object wordt gemaakt opnieuw te parseren, kan het prototypepatroon worden gebruikt om het originele object eenvoudig te dupliceren wanneer er een nieuw object nodig is.

Stel ook dat het object gegevens kan bevatten die grote hoeveelheden geheugen in beslag nemen, zoals gegevens die afbeeldingen vertegenwoordigen. Het geheugen kan worden verminderd door gebruik te maken van een copy-on-write-overerving, waarbij de originele, niet-gedupliceerde gegevens worden weergegeven totdat de code probeert die gegevens te wijzigen. Vervolgens worden de nieuwe gegevens gemaskeerd om te verwijzen naar de originele gegevens.


Antwoord 2, autoriteit 67%

Het prototypepatroon is een creatiepatroon dat is gebaseerd op het klonen van een vooraf geconfigureerd object. Het idee is dat je een object kiest dat is geconfigureerd voor de standaard of in de marge van een specifieke use-case en vervolgens kloon je dit object en configureert het naar je exacte behoeften.

Het patroon is handig om een ​​heleboel boilerplate-code te verwijderen, wanneer de vereiste configuratie lastig zou zijn. Ik beschouw Prototypes als een vooraf ingesteld object, waarbij je een aantal staten opslaat als een nieuw startpunt.


Antwoord 3, autoriteit 22%

Veel van de andere antwoorden hier gaan over de kostenbesparingen van het klonen van een reeds geconfigureerd object, maar ik zou graag willen ingaan op het andere “punt” van het prototypepatroon. In sommige talen, waar klassen worden behandeld als eersteklas objecten, kunt u configureren welk type object tijdens runtime door een client wordt gemaakt door het simpelweg de klassenaam door te geven. In talen als C++, waar klassen niet worden behandeld als eersteklas objecten, kun je met het prototypepatroon hetzelfde effect bereiken.

Stel dat we bijvoorbeeld een Chefhebben in een restaurant wiens taak het is om maaltijden te bereiden en te serveren. Laten we zeggen dat de Chefonderbetaald en ontevreden is, dus hij maakt gerechten zoals de volgende:

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...
        }
};

Laten we zeggen dat we de Chefwillen veranderen in een opzichtige beroemde chef-kok. Dit betekent dat hij/zij verschillende gerechten moet newin prepareMeal(). We willen de methode aanpassen zodat de soorten maaltijden die newworden door de Chefgespecificeerd kunnen worden als parameters. In andere talen waar klassen eersteklas objecten zijn, kunnen we de klassenamen eenvoudig als parameters doorgeven aan de methode. We kunnen dit niet doen in C++, dus we kunnen profiteren van het prototypepatroon:

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...
        }
};

Houd er rekening mee dat een methode clone()een instantie van het afgeleide type maakt, maar een verwijzing naar het bovenliggende type retourneert. Dit betekent dat we het type object dat wordt gemaakt kunnen wijzigen door een ander afgeleid type te gebruiken, en de klant zal het verschil niet weten. Dit ontwerp stelt ons nu in staat om een ​​Chef— de klant van onze Prototypes — te configureren om tijdens runtime verschillende soorten gerechten te maken:

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);

Je vraagt ​​je misschien af ​​dat je met het Prototype-patroon hetzelfde koopt als het Factory Method-patroon, dus waarom zou je dat niet gewoon gebruiken? Omdat het patroon van de fabrieksmethode een hiërarchie van schepperklassen zou vereisen die de hiërarchie van producten die worden gemaakt weerspiegelen; dwz we hebben een MozzarellaSticksWithKetchupCreatornodig met een make()methode, een HockeyPuckHamburgerWithSoggyFriesCreatormet een make()methode, enzovoorts. Je zou het prototypepatroon daarom eenvoudig kunnen zien als een manier om de coderedundantie te verminderen die vaak wordt geïntroduceerd door het patroon van de fabrieksmethode.

Dit argument is ontleend aan Design Patterns: Elements of Reusable Object-Oriented Software, ook wel het boek “Gang of Four” genoemd.


Antwoord 4, autoriteit 10%

Als u een object wilt maken, maar niet de dure procedure voor het maken van objecten wilt doorlopen waarbij netwerk- of database-aanroepen worden gedaan, gebruik dan het prototypepatroon. Maak gewoon een kopie van het object en breng uw wijzigingen daarin aan.


Antwoord 5, autoriteit 2%

het gebruik van een prototypepatroon is volledig afhankelijk van uw probleem. In de meeste gebruikelijke gevallen is er geen verschil tussen klonen en het maken van een nieuw object.
MAARals u een aantal complexe of tijdrovende bewerkingen uitvoert in de constructor of bij het instellen van een eigenschap en het moet complexe en tijdrovende bewerkingen uitvoeren, dan zal het prototypepatroon ons helpen. Omdat het kopiëren van objecten van een oude instantie naar een nieuwe instantie eenvoudiger is en de prestaties hoger zijn (diep klonen). Dit patroon is dus beter compatibel met objecten, omdat hun toestand lange tijd niet is gewijzigd.
Analyseer uw probleem volledig voordat u dit patroon gebruikt.


Antwoord 6

Vergeleken met het abstracte fabriekspatroon hoeft u door het prototypepatroon te gebruiken geen grote fabriekshiërarchie te hebben, alleen een grote producthiërarchie.


Antwoord 7

Als u een vereiste heeft, waarbij u dezelfde gegevens met Object herhaalbaar moet invullen of gebruiken

en

Het is niet mogelijk om bijvoorbeeld uit het bestaande object te bouwen [Bouwobject met behulp van netwerkstroom]
of

Om een object te bouwen, is tijdrovend [bouwen van een groot object, door gegevens uit database te krijgen] Gebruik dan dit ontwerppatroon, zoals in dit een kopie is het bestaande object gemaakt, deze kopie is anders dan het originele object en kan net als originele worden gebruikt.

Other episodes