What Is the Prototype Pattern?
Use the prototype instance to specify the kind of object to be created, and create a new object by copying these prototypes.
- The prototype pattern is a creational design pattern. The prototype pattern allows an object to create another customizable object without knowing any details about how to create it. The working principle is: by passing a prototype object to the object to be created The object to be launched is created by requesting the prototype object to copy itself. [1]
- The main problems it faces are: the creation of "some complex structured objects"; due to changes in requirements, these objects often face drastic changes, but they have relatively stable and consistent interfaces. [2]
- Because the clone () method is provided in Java to achieve the cloning of objects, the implementation of the prototype mode becomes very simple at once.
- Take a spoon as an example:
public abstract class AbstractSpoon implements Cloneable { String spoonName; public void setSpoonName (String spoonName) {this.spoonName = spoonName;} public String getSpoonName () {return this.spoonName;} public Object clone () { Object object = null; try { object = super.clone (); } catch (CloneNotSupportedException exception) { System.err.println ("AbstractSpoon is not Cloneable"); } return object; } } There are two concrete implementations (ConcretePrototype): public class SoupSpoon extends AbstractSpoon { public SoupSpoon () { setSpoonName ("Soup Spoon"); } }
- Calling prototype mode is simple:
AbstractSpoon spoon = new SoupSpoon (); AbstractSpoon spoon = new SaladSpoon ();
- Of course, you can also combine the factory pattern to create an AbstractSpoon instance.
- In Java, the prototype pattern becomes the use of the clone () method. Because of Java's pure object-oriented characteristics, the use of design patterns in Java becomes very natural. This is reflected in many patterns, such as the Iterator traversal pattern.
- Prototype mode with prototype manager: Client role: The client class makes a request to the prototype manager to create an object.
- Abstract prototype role: This is an abstract role, usually implemented by a C # interface or abstract class. This role gives all the interfaces required by the concrete prototype class. In C #, the abstract prototype role usually implements the ICloneable interface.
- Concrete Prototype role: the object being copied. This role needs to implement the interfaces required by the abstract prototype role.
- Prototype Manager (Prototype Manager) role: create objects of a specific prototype class, and record each created object. [1]
- The code is implemented as follows:
/ CplusplusPrototype.cpp: Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <vector> #include <assert.h> usingnamespace std; // parent class Resume { protected: char * name; public: Resume () {} virtual ~ Resume () {} virtual Resume * Clone () {return NULL;} virtualvoid Set (char * n) {} virtualvoid Show () {}}; class ResumeA : public Resume {public: ResumeA (constchar * str); // Constructor ResumeA (const ResumeA & r); // Copy constructor ~ ResumeA (); // Destructor ResumeA * Clone (); // Clone, the key Where void Show (); // display content}; ResumeA :: ResumeA (constchar * str) {if (str == NULL) {name = newchar [1]; name [0] = '\ 0';} else { name = newchar [strlen (str) +1]; strcpy (name, str);}} ResumeA :: ~ ResumeA () {delete [] name;} ResumeA :: ResumeA (const ResumeA & r) {name = newchar [strlen (r.name) +1]; strcpy (name, r.name);} ResumeA * ResumeA :: Clone () {returnnew ResumeA (* this);} void ResumeA :: Show () {cout << "ResumeA name : "<< name << endl;} class ResumeB: public Resume {public: ResumeB (constchar * str); // Constructor ResumeB (const ResumeB & r); // Copy constructor ~ ResumeB (); // Destructor ResumeB * Clone (); // Clone, the key is void Show (); // Display content}; ResumeB :: ResumeB (constchar * str) {if (str == NULL) {name = newchar [1]; name [0] = '\ 0';} else {name = newchar [strlen (str) +1]; strcpy (name, str);}} ResumeB :: ~ ResumeB () {delete [] name;} ResumeB :: ResumeB (const ResumeB & r) {name = newchar [strlen ( r.name) +1]; strcpy (name, r.name);} ResumeB * ResumeB :: Clone () {returnnew ResumeB (* this);} void ResumeB :: Show () {cout << "ResumeB name: "<< name << endl;} class ResumeManager {private: vector <Resume *> mResume; public: ResumeManager () {} void add (Resume * resume) {mResume.push_back (resume);} Resume * get (int index ) const {assert (index> = 0 && index <mResume.size ()); return mResume [index];}}; int _tmain (int argc, _TCHAR * argv []) {ResumeManager * manager = new ResumeManager (); Resume * r1 = new ResumeA ("A"); Resume * r2 = new ResumeB ("B") ; manager-> add (r1); manager-> add (r2); manager-> get (0)-> Show (); manager-> get (1)-> Show (); Resume * r3 = manager-> get (0)-> Clone (); Resume * r4 = manager-> get (1)-> Clone (); // Delete r1, r2 delete r1; delete r2; r1 = r2 = NULL; // Deep copy so No effect on r3, r4 r3-> Show (); r4-> Show (); delete r3; delete r4; r3 = r4 = NULL; return 0;}