Download as pdf or txt
Download as pdf or txt
You are on page 1of 12

Creational Design Patterns:

In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to
create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or
added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation.

Creational design patterns are composed of two dominant ideas. One is encapsulating knowledge about which concrete
classes the system uses. Another is hiding how instances of these concrete classes are created and combined.

Creational design patterns are further categorized into Object-creational patterns and Class-creational patterns, where
Object-creational patterns deal with Object creation and Class-creational patterns deal with Class-instantiation. In greater
details, Object-creational patterns defer part of its object creation to another object, while Class-creational patterns defer
its object creation to subclasses.

Abstract Factory Pattern:


The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without
specifying their concrete classes.

AbstractFactory: declares an interface for operations that create abstract products

ConcreteFactory: implements the operations to create concrete product objects

AbstractProduct: declares an interface for a type of product object

Product: defines a product object to be created by the corresponding concrete factory implements the AbstractProduct
interface

Client: uses interfaces declared by AbstractFactory and AbstractProduct classes

Page 1 of 12
C# Example 1:

Creating the Abstract Products


In our case, we need two abstract products ISmart and IDumb.

interface IDumb
{
string Name();
}
interface ISmart
{
string Name();
}

Creating the Concrete Products

class Asha : IDumb


{
public string Name()
{
return "Asha";
}
}

class Primo : IDumb


{
public string Name()
{
return "Guru";
}
}

class Genie : IDumb


{
public string Name()
{
return "Genie";
}
}

class Lumia : ISmart


{
public string Name()
{
return "Lumia";
}
}

class GalaxyS2 : ISmart


{
public string Name()
{
return "GalaxyS2";
}
}

class Titan : ISmart


{
public string Name()
{
return "Titan";
}
}

Page 2 of 12
So we have all the concrete classes ready for all the Dumb Phones and smart phones irrespective of their
manufacturers.

Creating the Abstract Factory

Now the way we associate these Concrete products with their manufacturers is using the Concrete factories. But before
having the concrete factories, we need to have an Abstract Factory.

interface IPhoneFactory //'I' stands for interface no relation with Iphone


{
ISmart GetSmart();
IDumb GetDumb();
}

Creating the Concrete Factories

Now we can create our Concrete Factories for each manufacturer:

class SamsungFactory : IPhoneFactory


{
public ISmart GetSmart()
{
return new GalaxyS2();
}

public IDumb GetDumb()


{
return new Primo();
}
}

class HTCFactory : IPhoneFactory


{
public ISmart GetSmart()
{
return new Titan();
}

public IDumb GetDumb()


{
return new Genie();
}
}

class NokiaFactory : IPhoneFactory


{
public ISmart GetSmart()
{
return new Lumia();
}

public IDumb GetDumb()


{
return new Asha();
}
}

Page 3 of 12
Creating the Client
Now we have all the Abstract product classes ready, all the Concrete Product classes ready. Our Abstract Factory is
ready and all the Concrete Factories are ready. Now we can write client that will use this hierarchy of related products
to create the products.

enum MANUFACTURERS
{
SAMSUNG,
HTC,
NOKIA
}
class PhoneTypeChecker
{
ISmart sam;
IDumb htc;
IPhoneFactory factory;
MANUFACTURERS manu;

public PhoneTypeChecker(MANUFACTURERS m)
{
manu = m;
}

public void CheckProducts()


{
switch (manu)
{
case MANUFACTURERS.SAMSUNG:
factory = new SamsungFactory();
break;
case MANUFACTURERS.HTC:
factory = new HTCFactory();
break;
case MANUFACTURERS.NOKIA:
factory = new NokiaFactory();
break;
}

Console.WriteLine(manu.ToString() + ":\nSmart Phone: " +


factory.GetSmart().Name() + "\nDumb Phone: " + factory.GetDumb().Name());
}
}

static void Main(string[] args)


{
PhoneTypeChecker checker = new PhoneTypeChecker(MANUFACTURERS.SAMSUNG);

checker.CheckProducts();

Console.ReadLine();

checker = new PhoneTypeChecker(MANUFACTURERS.HTC);

checker.CheckProducts();
Console.ReadLine();

checker = new PhoneTypeChecker(MANUFACTURERS.NOKIA);

checker.CheckProducts();
Console.Read();
}

Now we can say we have a basic skeleton for the Abstract factory pattern ready. The concrete products here are not
telling anything but names of products but they can contain more information too. Before we end the show, we can
have a class diagram for the classes we created so that we can use this to map it with the GOFs diagram.

Page 4 of 12
Example 2:

public interface IProcessor


{
void PerformOperation();
}
public interface IHardDisk { void StoreData(); }
public interface IMonitor { void DisplayPicture();}

public class ExpensiveProcessor : IProcessor


{
public void PerformOperation()
{
Console.WriteLine("Operation will perform quickly");
}
}
public class CheapProcessor : IProcessor
{
public void PerformOperation()
{
Console.WriteLine("Operation will perform Slowly");
}
}

public class ExpensiveHDD : IHardDisk


{
public void StoreData()
{
Console.WriteLine("Data will take less time to store");
}
}
public class CheapHDD : IHardDisk
{
public void StoreData()
{
Console.WriteLine("Data will take more time to store");
}
}

public class HighResolutionMonitor : IMonitor


{
public void DisplayPicture()
{
Console.WriteLine("Picture quality is Best");
}
}
public class LowResolutionMonitor : IMonitor
{
public void DisplayPicture()
{
Console.WriteLine("Picture quality is Average");}}

Page 5 of 12
Factory Code will be as follows
public interface IMachineFactory
{
IProcessor GetRam();
IHardDisk GetHardDisk();
IMonitor GetMonitor();
}

public class HighBudgetMachine : IMachineFactory


{
public IProcessor GetRam() { return new ExpensiveProcessor(); }
public IHardDisk GetHardDisk() { return new ExpensiveHDD(); }
public IMonitor GetMonitor() { return new HighResolutionMonitor(); }
}
public class LowBudgetMachine : IMachineFactory
{
public IProcessor GetRam() { return new CheapProcessor(); }
public IHardDisk GetHardDisk() { return new CheapHDD(); }
public IMonitor GetMonitor() { return new LowResolutionMonitor(); }
}
//Let's say in future...Ram in the LowBudgetMachine is decided to upgrade then
//first make GetRam in LowBudgetMachine Virtual and create new class as follows

public class AverageBudgetMachine : LowBudgetMachine


{
public override IProcessor GetRam()
{
return new ExpensiveProcessor();
}
}

public class ComputerShop


{
IMachineFactory category;
public ComputerShop(IMachineFactory _category)
{
category = _category;
}
public void AssembleMachine()
{
IProcessor processor = category.GetRam();
IHardDisk hdd = category.GetHardDisk();
IMonitor monitor = category.GetMonitor();
//use all three and create machine

processor.PerformOperation();
hdd.StoreData();
monitor.DisplayPicture();
}
}

//Client Code
IMachineFactory factory = new HighBudgetMachine();// Or new LowBudgetMachine();
ComputerShop shop = new ComputerShop(factory);
shop.AssembleMachine();

Page 6 of 12
Factory Method Pattern:

Simple Factory and Factory Method


For our discussion let’s have a small problem statement.

Class structure

public interface ICustomer


{
void AddPoints();
void AddDiscount();
}

public class GoldCustomer : ICustomer


{
public void AddPoints()
{
Console.WriteLine("Gold Customer - Points Added");
}

public void AddDiscount()


{
Console.WriteLine("Gold Customer - Discount Added");
}

public void GoldOperation()


{
Console.WriteLine("Operation specific to Gold Customer");
}
}

public class SilverCustomer : ICustomer


{
public void AddPoints()
{
Console.WriteLine("Silver Customer - Points Added");
}

public void AddDiscount()


{
Console.WriteLine("Silver Customer - Discount Added");
}

public void SilverOperation()


{
Console.WriteLine("Operation specific to Silver Customer");
}
}

Problem Statement

Client want to create Customer Object (either Gold or Silverbased on requirement).

Page 7 of 12
Simple Factory
This is one of the pattern not born from GOF and most of the peopleconsiders this as the default Factory method
pattern. Here, we will just take out object creation process out of the client code and put into some other class. Look at
the code demonstration.
class CustomerFactory
{
public static ICustomer GetCustomer(int i)
{
switch (i)
{
case 1:
GoldCustomer goldCustomer = new GoldCustomer();
goldCustomer.GoldOperation();
goldCustomer.AddPoints();
goldCustomer.AddDiscount();
return goldCustomer;
case 2:
SilverCustomer silverCustomer = new SilverCustomer();
silverCustomer.SilverOperation();
silverCustomer.AddPoints();
silverCustomer.AddDiscount();
return silverCustomer;
default: return null;
}
}
}

//Client Code
ICustomer c = CustomerFactory.GetCustomer(someIntegerValue);

Factory Method Pattern

In this pattern we define an interface which will expose a method which will create objects for us. Return type of that
method is never be a concrete type rather it will be some interface (or may be an abstract class)

public abstract class BaseCustomerFactory


{
public ICustomer GetCustomer()
{
ICustomer myCust = this.CreateCustomer();
myCust.AddPoints();
myCust.AddDiscount();
return myCust;
}
public abstract ICustomer CreateCustomer();
}

public class GoldCustomerFactory : BaseCustomerFactory


{
public override ICustomer CreateCustomer()
{
GoldCustomer objCust = new GoldCustomer();
objCust.GoldOperation();
return objCust;
}
}
public class SilverCustomerFactory : BaseCustomerFactory
{
public override ICustomer CreateCustomer()
{
SilverCustomer objCust = new SilverCustomer();
objCust.SilverOperation();
return objCust;
}
}
//Client Code
BaseCustomerFactory c = new GoldCustomerFactory();// Or new SilverCustomerFactory();
ICustomer objCust = c.GetCustomer();
Page 8 of 12
Singleton Pattern:
The singleton pattern is a design pattern that restricts the instantiation of a class to one object. This is useful when exactly
one object is needed to coordinate actions across the system.

using System;

class SingletonPattern {

// Singleton Pattern Judith Bishop Dec 2006


// The public property protects the private constructor

public sealed class Singleton {


// Private Constructor
Singleton() { }

// Private object instantiated with private constructor


static readonly Singleton instance = new Singleton();

// Public static property to get the object


public static Singleton UniqueInstance {
get { return instance;}
}
}

static void Main() {


Singleton s1 = Singleton.UniqueInstance;
Singleton s2 = Singleton.UniqueInstance;

if (s1 == s2) {
Console.WriteLine("Objects are the same instance");
}
}
}

Lazy Initialization:
public class SingletonDemo {
private static SingletonDemo instance = null;
private SingletonDemo() { }
public static synchronized SingletonDemo getInstance() {
if (instance == null) {
instance = new SingletonDemo();
}
return instance;
}}
Eager initialization
public class Singleton {
private static final Singleton INSTANCE = new Singleton();

private Singleton() {}

public static Singleton getInstance() {


return INSTANCE;
}
}

Page 9 of 12
Behavioural Design Patterns:

Command Pattern:
definition

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests,
and support undoable operations.

participants

The classes and/or objects participating in this pattern are:

• Command (Command)
o declares an interface for executing an operation
• ConcreteCommand (CalculatorCommand)
o defines a binding between a Receiver object and an action
o implements Execute by invoking the corresponding operation(s) on Receiver
• Client (CommandApp)
o creates a ConcreteCommand object and sets its receiver
• Invoker (User)
o asks the command to carry out the request
• Receiver (Calculator)
o knows how to perform the operations associated with carrying out the request.

Page 10 of 12
Example Code:

using System;
using System.Collections.Generic;

namespace CommandPattern
{
public interface ICommand
{
void Execute();
}

/* The Invoker class */


public class Switch
{
private List<ICommand> _commands = new List<ICommand>();

public void StoreAndExecute(ICommand command)


{
_commands.Add(command);
command.Execute();
}
}

/* The Receiver class */


public class Light
{
public void TurnOn()
{
Console.WriteLine("The light is on");
}

public void TurnOff()


{
Console.WriteLine("The light is off");
}
}

/* The Command for turning on the light - ConcreteCommand #1 */


public class FlipUpCommand : ICommand
{
private Light _light;

public FlipUpCommand(Light light)


{
_light = light;
}

public void Execute()


{
_light.TurnOn();
}
}

Page 11 of 12
/* The Command for turning off the light - ConcreteCommand #2 */
public class FlipDownCommand : ICommand
{
private Light _light;

public FlipDownCommand(Light light)


{
_light = light;
}

public void Execute()


{
_light.TurnOff();
}
}

/* The test class or client */


internal class Program
{
public static void Main(string[] args)
{
Light lamp = new Light();
ICommand switchUp = new FlipUpCommand(lamp);
ICommand switchDown = new FlipDownCommand(lamp);

Switch s = new Switch();


string arg = args.Length > 0 ? args[0].ToUpper() : null;
if (arg == "ON")
{
s.StoreAndExecute(switchUp);
}
else if (arg == "OFF")
{
s.StoreAndExecute(switchDown);
}
else
{
Console.WriteLine("Argument \"ON\" or \"OFF\" is required.");
}
}
}
}

Page 12 of 12

You might also like