How to use the prototype design pattern in .NET

The prototype design pattern enables you to create new instances by copying existing instances to avoid the overhead involved in creating objects that can consume more resources

How to use the prototype design pattern in .NET
Thinkstock

Design patterns are used to solve recurring problems and complexities in software development. The prototype pattern belongs to the creational design patterns category and is used to create a clone of an object. Creational design patterns are concerned with object creation and managing the object creation process in your application. Typical examples of the design patterns that fall under the creational patterns category include the abstract factory, builder, factory method, prototype, and singleton patterns.

The prototype design pattern enables you to create a new instance of a class from an existing instance. You can take advantage of this design pattern to create a clone of an object when the object creation process itself is a costly affair. Note that cloning is defined as the process of creating an exact copy of an object. There are two types of cloning: deep copy and shallow copy.

Shallow copy vs. deep copy cloning

Shallow copy is performed using the Object.MemberwiseClone method and copies the non-static fields of an object, whereas deep copy is used to copy both the reference and value types and gives you a distinct instance on an object. You can learn more deep copy and shallow copy from my article here.

The participants (classes and objects) in a typical implementation of the prototype pattern include the following:

  • Prototype — this defines an interface for cloning itself
  • ConcretePrototype — this defines a type that implements the operation for cloning itself
  • Client — this defines the consumer that can create a new instance by cloning a prototype

Keeping this in mind, we will implement the prototype pattern here using three types. These include the following:

  • Customer
  • CustomerManager
  • CustomerPrototype

Create a prototype abstract class in .NET

Refer to the CustomerPrototype class given below.

[Serializable()]
public abstract class CustomerPrototype
    {
        public abstract CustomerPrototype Clone(bool performDeepCopy);
    }

The CustomerPrototype class is abstract in nature and contains one abstract method named Clone. This method accepts a boolean parameter named performDeepCopy. If the parameter passed to it is true, it will perform a deep copy, shallow copy otherwise.

Create a concrete prototype class in .NET

The CustomerManager class is given next. It contains a Dictionary that stores the instances of the Customer class (it is just another POCO class) inside it. It also contains an indexer named CustomerPrototype. The set property of the indexer is used to store data into the Dictionary instance named customers.

  public class CustomerManager
    {
     private Dictionary<int, CustomerPrototype> customers = new Dictionary<int, CustomerPrototype>();
        public CustomerPrototype this[int index]
        {
            get { return customers[index]; }
            set { customers.Add(index, value); }
        }
    }

Create a prototype client class in .NET

The Customer class is given next. It contains two properties, namely FirstName and LastName, and two methods, Clone and DeepCopy.

[Serializable()]
    public class Customer : CustomerPrototype
    {
        public string FirstName
        {
            get;set;
        }
        public string LastName
        {
            get; set;
        }
        public override CustomerPrototype Clone(bool deepClone)
        {
            switch (deepClone)
            {
                case true:
                    return this.DeepCopy<Customer>(this) as CustomerPrototype;
                case false:
                    return this.MemberwiseClone() as CustomerPrototype;
                default:
                    return this.MemberwiseClone() as CustomerPrototype;
            }
        }
        private T DeepCopy<T>(T obj)
        {
           //Write code here to perform deep copy.
        }
     }

I’ve skipped the source code of the DeepCopy method in the above code listing as it is already available in my earlier article here.

Create a deep copy of an object in .NET

The following code snippet illustrates how you can take advantage of the CustomerManager class we created earlier to perform a deep copy.

CustomerManager customerManager = new CustomerManager();
Customer custObj1 = new Customer();
custObj1.FirstName = "Joydip";
custObj1.LastName = "Kanjilal";
customerManager[0] = custObj1;
Customer custObj2 = new Customer();
custObj2.FirstName = "Stephen";
custObj2.LastName = "Smith";
customerManager[1] = custObj2;
Customer customer = customerManager[0].Clone(true) as Customer;

Note that we have passed “true” as a parameter to the Clone method to perform a deep copy.

Create a shallow copy of an object in .NET

Similarly, you could pass “false” as a parameter to the same method to perform a shallow copy. Here’s how you can achieve this.

Customer customer = customerManager[0].Clone(false) as Customer;

Finally, here is the complete code of the Main method for your reference.

static void Main(string[] args)
      {
      CustomerManager customerManager = new CustomerManager();
      Customer custObj1 = new Customer();
      custObj1.FirstName = "Joydip";
      custObj1.LastName = "Kanjilal";
      customerManager[0] = custObj1;
      Customer custObj2 = new Customer();
      custObj2.FirstName = "Stephen";
      custObj2.LastName = "Smith";
      customerManager[1] = custObj2;
      Customer customer = customerManager[0].Clone(true) as Customer;
      Console.ReadKey();
      }

Copyright © 2017 IDG Communications, Inc.