Creational Design Pattern in .NET

dotnet design patterns

Software design patterns provide an architecture or template used to design and solve recurring software problems and tasks. Applying time-tested patterns result in inextensible, maintainable and flexible high-quality code, shows superior craftsmanship of a software engineer. Being well-versed in the knowledge of design patterns allows one to spot brittle and immature code from miles away.

The Creational Design Pattern deals with object creation mechanisms, trying to create objects in a manner suitable to the situation.

The Creational Design Pattern deals with object creation mechanisms and trying to create objects in a manner suitable to the situation. It focuses on how the objects are created and utilized in an application. 

software design patterns

Factory Method Design Pattern

Factory method design pattern is one of the most used design pattern in .NET. It is used for solve the problem related to object creation.

It says that just define an interface or abstract class for creating an object but let the subclasses decide which class to instantiate. In other words, subclasses are responsible to create the instance of the class.

The Factory Method Pattern is also known as Virtual Constructor.

Example

interface Product {}	 
class ConcreteProductA : Product {}	 
class ConcreteProductB : Product {}	 

abstract class Creator
{
     public abstract Product FactoryMethod(string type);
}	 
class ConcreteCreator : Creator
{
     public override Product FactoryMethod(string type)
     {
	switch (type)
	{
	 case "A": return new ConcreteProductA();
 	 case "B": return new ConcreteProductB();
	 default: throw new ArgumentException("Invalid type", "type");
	}
     }
}

Abstract Factory Pattern

It’s used to create a set of related objects, or dependent objects. Abstract Factory use the factory for creating objects of several classes.

It is also FDP (Factory Design Pattern), BDP (Builder Design Pattern) and PDP (Prototype Design Pattern) for creating objects and it is depending on your requirement or choice.

Example

using System;
namespace AbstractFactoryPatternDemo {
 // AbstractProductA interface
 interface ILaptop {
  string Name();
 }
 // ProductA1
 class GamingLaptop: ILaptop {
  public string Name() {
   return "Gaming Laptop";
  }
 }
 // ProductA2
 class NormalLaptop: ILaptop {
  public string Name() {
   return "Normal Laptop";
  }
 }
 // AbstractProductB interface
 interface IDesktop {
  string Name();
 }
 // ProductB1
 class GamingDesktop: IDesktop {
  public string Name() {
   return "Gaming Desktop";
  }
 }
 // ProductB2
 class NormalDesktop: IDesktop {
  public string Name() {
   return "Normal Desktop";
  }
 }
 // AbstractFactory interface
 interface IComputerFactory {
  ILaptop GetLaptop(string laptopType);
  IDesktop GetDesktop(string desktopType);
 }
 // ConcreteFactoryA
 class LenovoFactory: IComputerFactory {
  public ILaptop GetLaptop(string laptopType) {
   switch (laptopType) {
    case "Gaming":
     return new GamingLaptop();
    case "Normal":
     return new NormalLaptop();
    default:
     throw new ApplicationException(laptopType + "type can not be created");
   }
  }
  public IDesktop GetDesktop(string DesktopType) {
   switch (DesktopType) {
    case "Gaming":
     return new GamingDesktop();
    case "Normal":
     return new NormalDesktop();
    default:
     throw new ApplicationException(DesktopType + "type can not be created");
   }
  }
 }

 // ConcreteFactoryB
 class DellFactory: IComputerFactory {
  public ILaptop GetLaptop(string laptopType) {
   switch (laptopType) {
    case "Gaming":
     return new GamingLaptop();
    case "Normal":
     return new NormalLaptop();
    default:
     throw new ApplicationException(laptopType + "type can not be created");
   }
  }
  public IDesktop GetDesktop(string DesktopType) {
   switch (DesktopType) {
    case "Gaming":
     return new GamingDesktop();
    case "Normal":
     return new NormalDesktop();
    default:
     throw new ApplicationException(DesktopType + "type can not be created");
   }
  }
 }
 // Client class
 class ComputerClient {
  ILaptop laptop;
  IDesktop desktop;
  public ComputerClient(IComputerFactory computerFactory, string computerType) {
   laptop = computerFactory.GetLaptop(computerType);
   desktop = computerFactory.GetDesktop(computerType);
  }
  public string GetLaptopName() {
   return laptop.Name();
  }
  public string GetDesktopName() {
   return desktop.Name();
  }
 }
 class Program {
  static void Main(string[] args) {
   IComputerFactory lenovoFactory = new LenovoFactory();
   IComputerFactory dellFactory = new DellFactory();

   ComputerClient lenovoClient = new ComputerClient(lenovoFactory, "Gaming");
   lenovoClient.GetLaptopName();
   lenovoClient.GetDesktopName();
   lenovoClient = new ComputerClient(lenovoFactory, "Normal");
   lenovoClient.GetLaptopName();
   lenovoClient.GetDesktopName();

   ComputerClient dellClient = new ComputerClient(dellFactory, "Gaming");
   dellClient.GetLaptopName();
   dellClient.GetDesktopName();
   dellClient = new ComputerClient(dellFactory, "Normal");
   dellClient.GetLaptopName();
   dellClient.GetDesktopName();
  }
 }
}

Builder Design Pattern

It is used to create complex type objects. It builds the complex object using some construction logic. It is implemented with step by step process. With different construction logic it will be create different complex object.

Same construction process can create different representations because separate the construction of a complex object from its representation.

Example

using System;
namespace BuilderPatternDemo
{
    // Product class
    class Laptop
    {
        public string ModelNumber { get; set; }
        public string Display { get; set; }
        public string RAM { get; set; }
        public string GraphicsCard { get; set; }
        public string TouchScreen { get; set; }
        public void PrintDetails ()
        {
            Console.WriteLine("----------- Laptop Details ----------------");
            Console.WriteLine("Model Number: {0}", ModelNumber);
            Console.WriteLine("Display: {0}", Display);
            Console.WriteLine("RAM: {0}", RAM);
            Console.WriteLine("Graphics Card: {0}", GraphicsCard);
            Console.WriteLine("Touch Screen: {0}", TouchScreen);
        }
    }
    // Builder interface
    interface ILaptopBuilder
    {
        void addModelNumber();
        void addDisplay();
        void addRAM();
        void addGraphicsCard();
        void addTouchScreen();

        Laptop getLaptop();
    }
    // ConcreteBuilder class - implements Builder interface
    class GamingLaptopBuilder : ILaptopBuilder
    {
        Laptop laptop = new Laptop();
        public void addModelNumber()
        {
            laptop.ModelNumber = "Gaming1001";
        }
        public void addDisplay()
        {
            laptop.Display = "Full HD display";
        }
        public void addRAM()
        {
            laptop.RAM = "16 GB";
        }
        public void addGraphicsCard()
        {
            laptop.GraphicsCard = "Nvidia GeForce";
        }
        public void addTouchScreen()
        {
            laptop.TouchScreen = "Yes";
        }
        public Laptop getLaptop()
        {
            return laptop;
        }
    }
    // ConcreteBuilder class - implements Builder interface
    class NormalLaptopBuilder : ILaptopBuilder
    {
        Laptop laptop = new Laptop();
        public void addModelNumber()
        {
            laptop.ModelNumber = "Normal1001";
        }
        public void addDisplay()
        {
            laptop.Display = "SD Display";
        }
        public void addRAM()
        {
            laptop.RAM = "2GB";
        }
        public void addGraphicsCard()
        {
            laptop.GraphicsCard = "No graphics card";
        }
        public void addTouchScreen()
        {
            laptop.TouchScreen = "NO";
        }
        public Laptop getLaptop()
        {
            return laptop;
        }
    }
    // Director class
    class LaptopManufacturer
    {
        public void BuildLaptop (ILaptopBuilder laptopBuilder)
        {
            laptopBuilder.addModelNumber();
            laptopBuilder.addDisplay();
            laptopBuilder.addRAM();
            laptopBuilder.addGraphicsCard();
            laptopBuilder.addTouchScreen();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            // create object of manufacturer
            LaptopManufacturer laptopManufacturer = new LaptopManufacturer();
            // build Gaming Laptop
            ILaptopBuilder gamingLaptopBuilder = new GamingLaptopBuilder();
            laptopManufacturer.BuildLaptop(gamingLaptopBuilder);
            Laptop GamingLaptop = gamingLaptopBuilder.getLaptop();
            // print details
            Console.WriteLine("Gaming Laptop Object:");
            GamingLaptop.PrintDetails();

            // build normal laptop
            ILaptopBuilder normalLaptopBuilder = new NormalLaptopBuilder();
            laptopManufacturer.BuildLaptop(normalLaptopBuilder);
            Laptop NormalLaptop = normalLaptopBuilder.getLaptop();
            // print details
            Console.WriteLine("\nNormal Laptop Object:");
            NormalLaptop.PrintDetails();
        }
    }
}

What will Google Fuchsia look like?

There are not any official announcements declared yet, but as per technology news and web information. We think Fuchsia will be the replacement for Google Chrome and Google Android OS platforms. The Github project is also available online to early users or developer who are eager to check Fuchsia’s early look.

Prototype Design Pattern

It is used to creating a duplicate object or clone of the current object pattern. Cloned objects can be processed in the program independently and will possess no relation to the original object. The creation of an object is costly or complex.

Example

using System;
namespace PrototypePatternDemo
{
    // IPrototype interface
    public interface IEmployee
    {
        // Method for cloning
        IEmployee Clone();
    }
    // ConcretePrototype1 class implements IPrototype interface
    public class PermanentEmployee : IEmployee
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string EmploymentType { get; set; }

        // Implement shallow cloning method
        public IEmployee Clone()
        {
            // Shallow Copy
            return this.MemberwiseClone() as IEmployee;

            // Deep Copy
            // Implement Memberwise clone method for every reference type object 
            // return ..
        }
    }
    public class TemporaryEmployee : IEmployee
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string EmploymentType { get; set; }

        // Implement shallow cloning method
        public IEmployee Clone()
        {
            // Shallow Copy 
            return this.MemberwiseClone() as IEmployee;

            // Deep Copy
            // Implement Memberwise clone method for every reference type object 
            // return ..
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            PermanentEmployee permanentEmployee = new PermanentEmployee();
            permanentEmployee.Name = "Sam";
            permanentEmployee.Age = 25;
            permanentEmployee.EmploymentType = "Permanent";

            // clone permanent employee object with Clone method
            // If you will not set the new value for any field the it will take the default value from original object
            PermanentEmployee permanentEmployeeClone = (PermanentEmployee)permanentEmployee.Clone();
            permanentEmployeeClone.Name = "Tom";
            permanentEmployeeClone.Age = 30;

            Console.WriteLine("Permanent Employee Details");
            Console.WriteLine("Name: {0}; Age: {1}; Employment Type: {2}", permanentEmployee.Name, permanentEmployee.Age, permanentEmployee.EmploymentType);

            Console.WriteLine("Cloned Permanent Employee Details");
            Console.WriteLine("Name: {0}; Age: {1}; Employment Type: {2}", permanentEmployeeClone.Name, permanentEmployeeClone.Age, permanentEmployeeClone.EmploymentType);
        }
    }
}

Singleton Pattern

It creates a class which has created one instance and provide a global point of access it. It is one of the simplest design patterns among all pattern. A class which is responsible for creating and maintaining its own unique instance. 

When to use it?

  • Exactly one instance of a class is required.
  • Controlled access to a single object is necessary.

Feature of singleton design pattern:

  • The constructor of the class should be private: You don’t want to create multiple instances of the class, hence the constructor of the class should be private.
  • The Member which will be responsible for instance creation will be public and static: It ensures that member of a class can be accessed globally.

Example

using System;
namespace SingletonPattern
{
    // create a public class
    public class Singleton
    {
        // make constructor private
        private Singleton ()
        {
        }
        // create private instance of singleton class
        private volatile static Singleton singletonObject;
        // Define locking object
        private static object lockObj = new Object();
        // static method to create instance of singleton class
        public static Singleton Instance()
        {
            if (singletonObject == null)
            {
                // lock will ensure only one instance of singleton class will be created even for multithreaded environment
                // Once a thread will enter the inside the method then it will be locked and no other thread can enter inside
                lock (lockObj)
                {
                    if (singletonObject == null)
                    {
                        singletonObject = new Singleton();
                    }
                }
            }
            return singletonObject;
        }
        // Public method to test singleton class
        public void DisplayMessage()
        {
            Console.WriteLine("This is instance of singleton class");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Singleton singleton = Singleton.Instance();
            singleton.DisplayMessage();
            Console.ReadLine();
        }
    }
}

With Software Design Patterns you’ll have the chance to do more than just read the theory. You’ll be able to dive deep into real problems and understand practical solutions with real-life code examples.

 

Dharmesh Kanzariya
Dharmesh Kanzariya
Diligent and result-oriented IT Professional with an experience of nearly 11 year of experience in Software Development in Dotnet, Java, Node.Js, Nest.Js . Knowledge of all phases of the Software Development Life Cycle from System analytics to deployment.
Related Posts