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.
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.