Design Mode (4) Prototype
1. Overview
We all know that the creation mode is generally used to create a new object, and then we use this object to complete some object operations, in the prototype mode, we can quickly create an object without providing special new () operations. This is undoubtedly a very effective method, quickly create a new object.
Example 1:Sun Wukong pulls out a monkey hair, and a little blow will become a lot of Sun Wukong.
Example 2:Send a courier
The following is a mailing scenario:
"Send me a courier ." Said the customer.
"To where? Sent ......?" You asked.
"It's almost the same as last time, but it's just sent to another address. Here is the mailing address ......" The customer said that he would give you a piece of paper with a mailing address.
"Good !" You agree happily, because you have saved the user's previous mail information. You just need to copy the data and then quickly create new express data through simple modifications.
2. Problem
When the object constructor is very complex and the new object is generated, it is time-consuming and resource-consuming? How can we create it?
3. SolutionCreate more objects of the same type by copying (cloning, copying) an object of the specified type. This specified object can be called a "prototype" object, that is, more objects of the same type can be obtained by copying the prototype object. That is, the prototype design mode. Clone is used in many php template libraries. For example, smarty. 4. Applicability
The main idea of the prototype mode is to clone a new object based on an existing object. Generally, a clone method is provided for an object, through which a copy of the object is returned, this method of object creation is different from the previous several types of creation modes, the factory model and abstract factory mentioned above are both the process of encapsulating specific new operations through the factory and returning a new object. Sometimes it is not worthwhile to create an object through the factory, especially in the following scenarios, the prototype mode may be simpler and more efficient.
• 1) when a system should be independent from its product creation, composition, and representation, prototype mode should be used.
• 2) when the class to be instantiated is specified at the runtime, for example, through dynamic loading;
• 3) to avoid creating a factory class level parallel to the product class level
• 4) When an instance of a class can only have one of several combinations of different States. Creating prototype and cloning them may be more convenient than manually instantiating this type with the appropriate state each time. (That is, when we are dealing with some objects relatively simple, and the difference between objects is very small, it may be very fixed when several attributes are different, we may be more appropriate to use the prototype mode ).
5. The structure prototype structure is shown on the following page:
6. Composition
Customer (Client) Role: Customer program that uses the prototype object
Prototype role: Specifies the interface that a Prototype object must implement (if deep copy is to be provided, clone must be implemented)
ConcretePrototype: derived from an abstract prototype, it is the object used by the customer program, that is, the object to be copied. This role must implement the interface required by the abstract prototype role.
7. Effect
The Prototype mode has the same effect as the Abstract Factory mode and Builder mode: It hides a specific product class from the customer, thus reducing the number of names that the customer knows. In addition, these modes allow customers to use classes related to specific applications without changing them.
The following lists some other advantages of the Prototype mode.
1) add and delete products at runtime: Prototype allows a new product class to be integrated into the system only by registering a Prototype instance with the customer. It is more flexible than other creation modes because customers can create and delete prototypes at runtime.
2) Change the value to specify a new object: a highly dynamic system allows you to define a new behavior through object composition-for example, by specifying a value for an object variable-and changing the new class. By instantiating existing classes and registering these instances as prototype of customer objects, You can effectively define objects of new classes. The customer can delegate their responsibilities to the prototype to demonstrate new behaviors. This design allows you to define a new "class" without programming ". In fact, cloning a prototype is similar to instantiating a class. The Prototype mode can greatly reduce the number of classes required by the system.
3) change the structure to specify new objects: many applications create objects by components and child parts.
4) Reduce the subclass construction. Factory Method often produces a Creator class level parallel to the product class level. The Prototype mode allows you to clone a Prototype instead of requesting a factory method to generate a new object. Therefore, you do not need the Creator class hierarchy. This advantage is mainly applicable to languages such as C ++ that do not use classes as level-1 class objects. Like Smalltalk and Objective
C has little benefit, because you can always use a class object as the creator. In these languages, class objects have played the same role as prototypes.
5) dynamically configure the runtime environment of the application using the class, allowing you to dynamically load the class into the application. In languages like C ++, Prototype is the key to using this function. An application that wants to create an instance for dynamically loading classes cannot reference the class constructor statically. The runtime environment should automatically create instances of each class during loading, and register the instance with the prototype Manager (see implementation section ). In this way, the application can request the instances of the newly loaded classes from the prototype manager. These classes are not originally connected to the program. E t ++ application framework [w g m 8] has a running system that uses this solution.
The main drawback of Prototype is that each Prototype subclass must implement clone operations, which may be very difficult. For example, it is difficult to add a clone operation when the specified class already exists. It may be difficult to clone objects that do not support copying or circular references.
8. Implementation
<? Php/*** Prototype mode ** // *** abstract Prototype role */interface Prototype {public function copy ();} /*** Prototype */class ConcretePrototype implements Prototype {private $ _ name; public function _ construct ($ name) {$ this-> _ name = $ name ;} public function setName ($ name) {$ this-> _ name = $ name;} public function getName () {return $ this-> _ name;} public function copy () {/** deep copy */return clone $ this;/** shallow copy * // return $ This ;}} class Client {/*** Main program. */public static function main () {$ object1 = new ConcretePrototype (11); $ object_copy = $ object1-> copy (); var_dump ($ object1-> getName ()); echo '<br/>'; var_dump ($ object_copy-> getName (); echo '<br/>'; $ object1-> setName (22 ); var_dump ($ object1-> getName (); echo '<br/>'; var_dump ($ object_copy-> getName (); echo '<br/> ';}} client: main ();?>
9. Shallow copy and deep copy
Schematic diagram of the prototype mode:
All variables of the Copied object in the shortest copy contain the same value as the original object, and the reference to other objects still points to the original object. That is, the shortest copy is only responsible for the current object instance and does not copy the referenced object. Situation of objects and object copies after the shortest copy:
Deep copy
All variables of the Copied object contain the same value as the original object, except those variables that reference other objects. Variables that reference other objects will point to a new object to be copied, instead of the original referenced objects. That is, the deep copy operation copies all the objects referenced by the objects to be copied. This kind of copy operation is called indirect copy. Objects and object copies of deep replication:
How many layers do deep copy have to go deep.
When you decide to copy an object in the deep copy mode, you must decide whether to use the shortest copy or deep copy for the indirect copy object or continue to use the deep copy object.
Therefore, when deep copy is adopted, the depth must be determined to be deep. In addition, circular references may occur during deep copy.
10. Prototype Manager
The second form of the prototype mode is the prototype mode with the prototype Manager. The UML diagram is as follows:
Prototype manager role: Creates objects of a specific prototype class and records each created object.
The following example demonstrates how to store a user-defined color prototype in the prototype Manager. The customer clones a color object through the prototype manager.
<? Php/*** abstract Prototype **/abstract class ColorPrototype {// Methodsabstract function copy ();} /*** Concrete Prototype **/class Color extends ColorPrototype {// Fieldsprivate $ red; private $ green; private $ blue; // Constructorsfunction _ construct ($ red, $ green, $ red) {$ this-> red = $ red; $ this-> green = $ green; $ this-> blue = $ red ;} /*** set red ** @ param unknown_type $ red */public function setRed ($ Red) {$ this-> red = $ red;}/*** get red **/public function getRed () {return $ this-> red ;} /*** set Green ** @ param $ green */public function setGreen ($ green) {$ this-> green = $ green ;} /*** get Green *** @ return unknown */public function getGreen () {return $ this-> green ;} /*** set Blue ** @ param $ Blue */public function setBlue ($ Blue) {$ this-> blue = $ Blue ;} /*** get Blue ** @ return unkn Own */public function getBlue () {return $ this-> blue;}/*** Enter description here... ** @ return unknown */function copy () {return clone $ this;} function display () {echo $ this-> red, ',', $ this-> green, ',', $ this-> blue, '<br>' ;}}/*** Enter description here... **/class ColorManager {// Fieldsstatic $ colors = array (); // Indexerspublic static function add ($ name, $ value) {self :: $ colors [$ name] = $ value ;} Public static function getCopy ($ name) {return self: $ colors [$ name]-> copy ();}} /*** Client **/class Client {public static function Main () {// prototype: white ColorManager: add ("white", new Color (255, 0, 0); // the red color can be obtained from the prototype white object, but the white color is modified again: r$ red = ColorManager: getCopy ('white '); $ red-> setRed (255); $ red-> display (); // the green color can be obtained from the prototype white object, but the white color is changed again: g $ green = ColorManager :: getCopy ('white'); $ green-> setGreen (255); $ green-> display (); // The green color can be obtained from the prototype white object, but the white color is modified again: B $ Blue = ColorManager: getCopy ('white'); $ Blue-> setBlue (255 ); $ Blue-> display () ;}} ini_set ('display _ errors ', 'on'); error_reporting (E_ALL &~ E_DEPRECATED); Client: Main ();?>