NET design pattern Part II creation mode (5): Prototype mode (Prototype pattern)

Source: Internet
Author: User

Prototype mode (Prototype pattern)

——. NET Design Pattern Series VI

TERRYLEE,2006 year January

Overview

In the software system, sometimes the product class is changed dynamically, and the product class has a certain hierarchical structure. If Factory mode is used, then the factory method class parallel to the product class hierarchy will also change with this change, which is obviously not appropriate. So how do you encapsulate this dynamic change? So that client programs that depend on these volatile objects do not change with the product class?

Intention

Use the prototype instance to specify the kind of object to create and create a new object by copying the prototypes.

Structure diagram

Prototype mode structure diagram

Examples of life

The prototype mode uses a prototype instance to specify the kind of object to create. The prototype of a new product is usually built before the entire product, and the prototype is passive and does not involve copying itself. The mitosis of a cell, which produces two of the same cells, is an example of a prototype that plays an active role in reproducing itself, which demonstrates the prototype pattern. A cell divides, producing two cells of the same genotype. In other words, the cells cloned themselves.

Prototype pattern object graph using the cell division example

Prototype Mode commentary

Let's consider a scenario where we're going to develop a palette where the user clicks on a palette and will return an instance of the corresponding color, and let's see how the prototype model can be designed to dynamically load specific products.

Naturally, we use OO ideas to take each color as an object and abstract a common parent class for them, such as:

Implementation code:

Public abstract class Color

{

public abstract void Display ();

}

public class Redcolor:color

{

public override void Display ()

{

Console.WriteLine ("Red ' s RGB Values are:255,0,0");

}

}

public class Greencolor:color

{

public override void Display ()

{

Console.WriteLine ("Green ' s RGB Values are:0,255,0");

}

}

The client program needs a certain color, just need to create a corresponding instance of the specific class. But then we don't get to the point of encapsulation change, and you might say that you can use the factory method pattern to define a factory class that is parallel to its class for each specific subclass, well, look at the implementation:

Implementation code:

Public abstract class Colorfactory

{

Public abstract Color Create ();

}

public class Redfactory:colorfactory

{

public override Color Create ()

{

return new Redcolor ();

}

}

public class Greenfactory:colorfactory

{

public override Color Create ()

{

return new Greencolor ();

}

}

After implementing this step, you can see that the client program just calls the factory method. It seems that there is no problem in using the factory method pattern to solve it. However, we consider only the packaging of new changes, without regard to the number of colors is constantly changing, and even may be in the process of the program to dynamically increase and decrease, then the implementation of this method, with the increasing number of colors, the number of subclasses will rapidly expand, resulting in too many sub-classes, It is obvious that the factory method model is somewhat inappropriate.

Further thinking, these color subclasses differ only in the initialized Color object category. Add a class such as Colortool to parameterize its instances, which are supported and created by color. We let Colortool create a new color by cloning or copying an instance of a color subclass, which is a prototype. As shown in the following:

Implementation code:

Abstract class Colorprototype

{

Public abstract Colorprototype Clone ();

}

Class Conctetecolorprototype:colorprototype

{

private int _red, _green, _blue;

public Conctetecolorprototype (int red, int green, int blue)

{

this._red = red;

This._green = green;

This._blue = blue;

}

public override Colorprototype Clone ()

{

Implement a shallow copy

Return (Colorprototype) this. MemberwiseClone ();

}

public void Display (string _colorname)

{

Console.WriteLine ("{0} ' s RGB Values are: {1},{2},{3}",

_colorname,_red, _green, _blue);

}

}

Class Colormanager

{

Hashtable colors = new Hashtable ();

Public Colorprototype this[string Name]

{

Get

{

Return (Colorprototype) colors[name];

}

Set

{

Colors. ADD (Name,value);

}

}

}

Now let's analyze what benefits this brings. First, the number of subclasses is greatly reduced, and there is no need to set a class for each specific color product and a factory method class that is parallel to its rank, while Colortool plays the role of the prototype manager. Look again at the implementation of the client program:

Class APP

{

public static void Main (string[] args)

{

Colormanager Colormanager = new Colormanager ();

Initialize Color

colormanager["Red"] = new Conctetecolorprototype (255, 0, 0);

colormanager["green"] = new Conctetecolorprototype (0, 255, 0);

colormanager["Blue" = new Conctetecolorprototype (0, 0, 255);

Colormanager["angry"] = new Conctetecolorprototype (255, 54, 0);

Colormanager["peace"] = new Conctetecolorprototype (128, 211, 128);

Colormanager["Flame"] = new Conctetecolorprototype (211, 34, 20);

Use color

String colorname = "Red";

Conctetecolorprototype C1 = (conctetecolorprototype) colormanager[colorname]. Clone ();

C1. Display (colorname);

ColorName = "Peace";

Conctetecolorprototype C2 = (conctetecolorprototype) colormanager[colorname]. Clone ();

C2. Display (colorname);

ColorName = "Flame";

Conctetecolorprototype C3 = (Conctetecolorprototype) colormanager[colorname]. Clone ();

C3. Display (colorname);

Console.ReadLine ();

}

}

As you can see, the client program can incorporate a specific product class into the system by registering the prototype instance, and at runtime, the prototype can be created and deleted dynamically. Finally, it is important to note that in the above example, a shallow copy is used. If you want to make a deep copy, you need to do it in a serialized way. After the above analysis, let's consider the following question:

1. Why do I need prototype mode?

The essence of introducing prototype mode is to use an existing prototype object to quickly generate the same instance as the prototype object. You have an instance of a a:a a = new A (); Now you want to generate an instance of the same as Car1 B, according to the prototype pattern, it should be this: a B = a.clone (); instead of re-creating a new A object. In this case, you can get an instance of the same as a and, to be exact, their data members are the same. The prototype mode also returns an A object without using the new operation.

2. What are the benefits of introducing the prototype model?

As you can see, the introduction of prototype mode eliminates the need for a factory method class that is parallel to the specific product hierarchy, reduces the construction of the class, and the client program can create and delete prototypes at runtime.

3. What object-oriented design principles does the prototype model meet?

Dependency Inversion principle: the example above, the prototype manager (Colormanager) relies only on the abstract part (Colorprototype), The specific implementation details (Conctetecolorprototype) are dependent on the abstract part (Colorprototype), so prototype is well satisfied with the dependency inversion principle.

Deep copy implementation via serialization

To implement a deep copy, you can serialize it in a way. Abstract classes and specific classes must be labeled as serializable [Serializable], the above example followed by a deep copy of the complete program as follows:

Using System;

Using System.Collections;

Using System.IO;

Using System.Runtime.Serialization;

Using System.Runtime.Serialization.Formatters.Binary;

[Serializable]

Abstract class Colorprototype

{

Public abstract Colorprototype Clones (bool deep);

}

[Serializable]

Class Conctetecolorprototype:colorprototype

{

private int _red, _green, _blue;

public Conctetecolorprototype (int red, int green, int blue)

{

this._red = red;

This._green = green;

This._blue = blue;

}

public override Colorprototype Clone (bool deep)

{

if (deep)

return Createdeepcopy ();

Else

Return (Colorprototype) this. MemberwiseClone ();

}

Enable deep copy

Public Colorprototype createdeepcopy ()

{

Colorprototype Colorprototype;

MemoryStream MemoryStream = new MemoryStream ();

BinaryFormatter formatter = new BinaryFormatter ();

Formatter. Serialize (MemoryStream, this);

memorystream.position = 0;

Colorprototype = (colorprototype) formatter. Deserialize (MemoryStream);

return colorprototype;

}

Public conctetecolorprototype Create (int red,int green,int blue)

{

return new Conctetecolorprototype (Red,green,blue);

}

public void Display (string _colorname)

{

Console.WriteLine ("{0} ' s RGB Values are: {1},{2},{3}",

_colorname,_red, _green, _blue);

}

}

Class Colormanager

{

Hashtable colors = new Hashtable ();

Public Colorprototype this[string Name]

{

Get

{

Return (Colorprototype) colors[name];

}

Set

{

Colors. ADD (Name,value);

}

}

}

Class APP

{

public static void Main (string[] args)

{

Colormanager Colormanager = new Colormanager ();

Initialize Color

colormanager["Red"] = new Conctetecolorprototype (255, 0, 0);

colormanager["green"] = new Conctetecolorprototype (0, 255, 0);

colormanager["Blue" = new Conctetecolorprototype (0, 0, 255);

Colormanager["angry"] = new Conctetecolorprototype (255, 54, 0);

Colormanager["peace"] = new Conctetecolorprototype (128, 211, 128);

Colormanager["Flame"] = new Conctetecolorprototype (211, 34, 20);

Use color

String colorname = "Red";

Conctetecolorprototype C1 = (conctetecolorprototype) colormanager[colorname]. Clone (FALSE);

C1. Display (colorname);

ColorName = "Peace";

Conctetecolorprototype C2 = (conctetecolorprototype) colormanager[colorname]. Clone (TRUE);

C2. Display (colorname);

ColorName = "Flame";

Conctetecolorprototype C3 = (Conctetecolorprototype) colormanager[colorname]. Clone (TRUE);

C3. Display (colorname);

Console.ReadLine ();

}

}

Implementation Essentials

1. The use of the prototype manager, reflected in the number of prototypes in a system is not fixed, can be dynamically created and destroyed, such as the above example of the color palette.

2. For cloning operations, you can use the MemberwiseClone () method of the object class in. NET to implement shallow copies of objects or to implement a deep copy in a serialized way.

3. The prototype pattern is also used to isolate the coupling between the consumer of a class object and the specific type (variable Class), which also requires these "variable classes" to have a stable interface.

Effect

1. It hides a specific product class from the customer, thus reducing the number of names the customer knows.

2. The prototype mode allows customers to incorporate a specific product class into the system only by registering a prototype instance, and customers can create and delete prototypes at run time.

3. Reduced subclass construction, the prototype pattern is to clone a prototype instead of requesting a factory method to create one, so it does not require a creater class hierarchy that is parallel to the specific product class.

4. The Portotype mode has the ability to dynamically load new functionality into an application. Due to the high independence of the prototype, it is easy to dynamically load new functions without affecting the old system.

5. The product class does not need to have any predetermined hierarchy structure, because the prototype mode is suitable for any hierarchy

6. The main disadvantage of the prototype pattern is that each class must be equipped with a clone method. And this cloning method requires a holistic view of the functionality of the class, which is not difficult for new classes, but it is not always easy to retrofit existing classes.

Applicability

The prototype mode should be used in the following cases:

1. When a system should be independent of its product creation, composition and presentation;

2. When the class to be instantiated is specified at run time, for example, by dynamic loading;

3. To avoid creating a plant class hierarchy that is parallel to the product class hierarchy;

4. When an instance of a class can have only one of several different state combinations. Building the corresponding number of prototypes and cloning them may be more convenient than manually instantiating the class each time you use the appropriate state.

Summarize

Prototype mode also hides the creation of objects from the client, but unlike constructing a new object by instantiating a class, the prototype pattern creates a new object by copying an existing object, reaching the " The purpose of isolating the coupling relationship between the consumer of the class object and the specific type (variable Class).

Reference documents

"Design Mode" (Chinese version)

"Designpatternsexplained"

Java and Patterns (Shanhong)

NET design pattern Part II creation mode (5): Prototype mode (Prototype pattern)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.