Thursday, January 24, 2008

Design Patterns - The Factory Method

Introduction


This article explains the Factory Method Pattern, which is one of the C# Design Patterns.

This pattern gives you the ability to create a factory (instance) that will instantiate many relatedobjects.



When to use the Factory Method?

  • A class can’t anticipate which kind of class of objects it must create.

  • A class uses its subclasses to specify which objects it creates.

  • You want to localize the knowledge of which class gets created.


Cooper - Introduction to Design Patterns in C#



You can think of this like if you have some different implementation for 1 parent object, and
then you have some other different creators for these instances.., so we will have a factory
that decides what creators and decide what instances does every creator instantiate.

The Pattern



Imagine we have a class called Message that sends some contents through the Send() function.

And we have some types of messages (Email, sms, .. etc.) each of which has a special implementation
of the send() function.

Now how to decide which type (instance) of message we will send if using a cell phone or a PC?

So, this means we have different machines (cell, PC, Laptop..), and each machine will instantiate
specific types of messages.


Message



  • The best way is to make an abstract class called Message and include an abstract method called Send(), So
    we can easily implement it.

    abstract class Message
    {
    abstract public void Send();
    }

  • Example of different implementations..

    class Email : Message
    {
    public override void Send()
    {
    Console.WriteLine(this.GetType().Name);
    }
    }
    class VoiceMail : Message
    {
    public override void Send()
    {
    Console.WriteLine(this.GetType().Name);
    }
    }
    class SMS : Message
    {
    public override void Send()
    {
    Console.WriteLine(this.GetType().Name);
    }
    }
    class MMS : Message
    {
    public override void Send()
    {
    Console.WriteLine(this.GetType().Name);
    }
    }

Machine


  • Now to make the machine.. Its the the factory that will decide which instances (types) of messages to instantiate,
    so if we have more than 1 machine, we can inherit from the machine and decide in the concrete factory.

    abstract class Machine
    {
    //The array of objects
    private List< Message > _messages = new List< Message >();
    public Machine()
    {
    CreateMachines();
    }

    //The function that each machine will override
    abstract public void CreateMachines();

    public List< Message > Messaages
    {
    get
    {
    return _messages;
    }
    }
    }

  • Cell Phone and PC example..

    class CellPhone : Machine
    {
    public override void CreateMachines()
    {
    //Instantiating objects
    Messaages.Add(new SMS());
    Messaages.Add(new MMS());
    }
    }

    class PC : Machine
    {
    public override void CreateMachines()
    {
    //Instantiating objects
    Messaages.Add(new Email());
    Messaages.Add(new VoiceMail());
    }
    }


  • And this how we can use the factory..

    class Program
    {
    static void Main(string[] args)
    {
    Machine[] machines = new Machine[2];
    //The constructor is the one who calls CreateMachine()
    machines[0] = new CellPhone();//A machine
    machines[1] = new PC();//Another machine..

    foreach (Machine _machine in machines)
    {
    Console.WriteLine("--" + _machine.GetType().Name);
    foreach (Message _message in _machine.Messaages)
    {
    _message.Send();
    }
    }
    }
    }




The Code



namespace Factory_Method
{
class Program
{
static void Main(string[] args)
{
Machine[] machines = new Machine[3];
machines[0] = new CellPhone();
machines[1] = new PC();
machines[2] = new Laptop();

foreach (Machine _machine in machines)
{
Console.WriteLine("--" + _machine.GetType().Name);
foreach (Message _message in _machine.Messaages)
{
_message.Send();
}
}
}
}
abstract class Message
{
abstract public void Send();
}

class Email : Message
{
public override void Send()
{
Console.WriteLine(this.GetType().Name);
}
}
class VoiceMail : Message
{
public override void Send()
{
Console.WriteLine(this.GetType().Name);
}
}
class SMS : Message
{
public override void Send()
{
Console.WriteLine(this.GetType().Name);
}
}
class MMS : Message
{
public override void Send()
{
Console.WriteLine(this.GetType().Name);
}
}

abstract class Machine
{
private List< Message > _messages = new List< Message >();
public Machine()
{
CreateMachines();
}

abstract public void CreateMachines();
public List< Message > Messaages
{
get
{
return _messages;
}
}
}

class CellPhone : Machine
{
public override void CreateMachines()
{
Messaages.Add(new SMS());
Messaages.Add(new MMS());
}
}

class PC : Machine
{
public override void CreateMachines()
{
Messaages.Add(new Email());
Messaages.Add(new VoiceMail());
}
}

class Laptop : Machine
{
public override void CreateMachines()
{
Messaages.Add(new Email());
Messaages.Add(new VoiceMail());
}
}


}

2 comments:

Amit said...

Thanks to islam ElDemery. It is a excellent piece of work from him. He helped me a lot.......

Michael.Nagy said...

nice job man .. begad gamed awi awi