The prototype
design pattern allows you to avoid
expensive initialization routines when you construct objects that are very
similar. The goal is to minimize the amount of work needed in creating
new objects when the initialization routines are expensive. For example, if the
initialization routine requires database queries, file lookups, or service
calls and you already have other objects in the system that are very similar to
the object you are constructing, then the prototype pattern may help you to
avoid those expensive initializations. |
Let's look at the UML of the prototype pattern first, then we will look an example to see how it works. Below is the UML of the Prototype Design Pattern:
- The PrototypeManager class is just a manager class that is used to add and retrieve prototypes by an index number, it has the following variable and methods:
- prototypeList variable is the collection that stores all the prototypes
- AddPrototype method allows you to add a prototype to the collection and assigning it an index number
- GetPrototype method allows you to retrieve a prototype from the collection using an index number
- The IPrototype interface specifies the methods that all prototype classes must implement. It has the Clone method that returns an IPrototype interface.
- The ConcretePrototype class is the actual prototype class, it implements the IPrototype interface and has the following property and method:
- copyProperty variable holds the information that is prepopulated. If the variable value is changed then the new instances created will have the new value.
- Clone method will make a copy of itself and return it. If the copyProperty is a value type (such as int or string) then you can just use shallow copy. If the copyProperty is a reference type (such as an object that contains other objects) then you will need to make deep copy of the variable.
While there are many supported ways of making shallow or deep copy of objects in various programming languages, for the purpose of understanding the prototype pattern we will not dig into such details but simply demonstrate the core concept of the prototype pattern.
A comparison between the prototype pattern and the flyweight pattern shows some similarities in the UML, in that both uses a manager to store and retrieve the objects in the collection. But there is a clear difference between the two. The prototype pattern is used to create new objects that are similar in nature (hence it's a creational pattern), while the flyweight pattern is used to allow the application to point to the same instance of the object to save memory (hence it's a structural pattern).
Let's see an example. In our example
we will often need to create Configuration
and UserProfile objects in the
application, and both objects stores information that are resource intensive
and takes a while to populate. The UML for the example is shown below:
The Configuration class has the fileInformation variable that takes a while to create. The same goes for the UserProfile class which has the databaseInformation variable that is resource intensive to create.
Below are the implementation code
and the output of the prototype pattern using our example. Notice that it takes
a while to create the prototype class for the first time, but subsequent objects created afterwards takes no time at all:
using System.Collections.Generic;
using System.Threading;
class Program
{
static void Main(string[] args)
{
Configuration c = new Configuration();
DateTime startTime = DateTime.Now;
c.GetFileInformation(); //takes long time to create the first time
DateTime endTime = DateTime.Now;
Console.WriteLine("First Configuration object took " + endTime.Subtract(startTime).TotalSeconds + " seconds");
UserProfile p = new UserProfile();
startTime = DateTime.Now;
p.GetDatabaseInformation(); //takes long time to create the first time
endTime = DateTime.Now;
Console.WriteLine("First UserProfile object took " + endTime.Subtract(startTime).TotalSeconds + " seconds");
//add prototypes to the manager
PrototypeManager manager = new PrototypeManager();
manager.AddPrototype(c, 0);
manager.AddPrototype(p, 1);
startTime = DateTime.Now;
(manager.GetPrototype(0).Clone() as Configuration).ShowInformation(); //new prototype copy
endTime = DateTime.Now;
Console.WriteLine("Second Configuration object took " + endTime.Subtract(startTime).TotalSeconds + " seconds");
startTime = DateTime.Now;
(manager.GetPrototype(1).Clone() as UserProfile).ShowInformation(); //new prototype copy
endTime = DateTime.Now;
Console.WriteLine("Second UserProfile object took " + endTime.Subtract(startTime).TotalSeconds + " seconds");
}
}
public interface IPrototype
{
IPrototype Clone();
}
public class PrototypeManager
{
//dictionary that holds the list of prototypes
private Dictionary<int, IPrototype> list = new Dictionary<int,IPrototype>();
public void AddPrototype(IPrototype p, int index)
{
list.Add(index, p); //add prototype to collection
}
public IPrototype GetPrototype(int index)
{
//return prototype from collection
return list[index].Clone();
}
}
public class Configuration : IPrototype
{
private string fileInformation;
public void GetFileInformation()
{
Thread.Sleep(5000); //takes 5 seconds to get information
fileInformation = "Long file information";
}
IPrototype IPrototype.Clone()
{
Configuration c = new Configuration(); //create new object
c.fileInformation = this.fileInformation; //copy value
return c;
}
public void ShowInformation()
{
Console.WriteLine("Showing " + fileInformation);
}
}
public class UserProfile : IPrototype
{
private string databaseInformation;
public void GetDatabaseInformation()
{
Thread.Sleep(5000); //takes 5 seconds to get information
databaseInformation = "Long database information";
}
IPrototype IPrototype.Clone()
{
UserProfile p = new UserProfile(); //create new object
p.databaseInformation = this.databaseInformation; //copy value
return p;
}
public void ShowInformation()
{
Console.WriteLine("Showing " + databaseInformation);
}
}
Future series of articles on sharepoint:
- sharepoint list -- the concepts of sharepoint list and how to effectively manage it
sharepoint version control -- the internals of sharepoint version control and how to administer and manage the versions
sharepoint permissions -- how to manage the permissions in a large enterprise sharepoint environment
sharepoint server farm -- how to set up a high availability sharepoint server farm
sharepoint document library -- the details on how to get your ways around the document library in sharepoint
sharepoint configuration -- the configurations needed for different sharepoint network scenarios
sharepoint css -- making the most out of customizing sharepoint frontend
sharepoint web services -- some of the most convienent ways to communicate with the internals of sharepoint