Wednesday, January 23, 2008

Design Patterns - Abstract Factory


Introduction:


This article explains the Abstract Factory pattern of the Design Patterns, and implements an example.
The Abstract Pattern is used to give you the ability to return one of related (grouped) objects of classes
through a factory object, The factory object can return one of a family classes and can also instantiate objects of
another family classes.



The Code


We are going to explain this on Investments, There is types of investment like stocks and bonds.
The investment itself can be raised and can fall, then the stocks investment for example can be raised and can fall.
This is done through the investment object (which is the factory).



The investment class is abstract, and has two abstract (not implemented) methods: CreateRaise(), and CreateFall() , each of which is type of
raiseInvestment and fallInvestment respectively.


abstract class invsetment
{
public abstract raiseInvestment CreateRaise();
public abstract fallInvestment CreateFall();
}

abstract class fallInvestment
{
public abstract int Minus(int current);
}

abstract class raiseInvestment
{
public abstract int Plus(int current);
}



So what I need now is to implement fallInvestment and raiseInvestment classes..



/// Beside Fall and Raise classes we can add
/// new class to calculate the interest related
/// changes for example, with a static method
/// to directly calculate the interest.

class Fall : fallInvestment
{
public override int Minus(int current)
{
return current - 1;
}
}

class Raise : raiseInvestment
{
public override int Plus(int current)
{
return current + 1;
}
}

Well, Now you have to decide what types of investments you want to make..

There can be Stocks and Bonds, each is an investment so each can inherits investment class.

To inherit investment class you have to override the CreateRaise() and CreateFall abstract
methods (which are in the investment class) and return a new instance of Raise and Fall classes.


class stocks : invsetment
{

public override raiseInvestment CreateRaise()
{
return new Raise();
}

public override fallInvestment CreateFall()
{
return new Fall();
}
}

class bonds : invsetment
{

public override raiseInvestment CreateRaise()
{
return new Raise();
}

public override fallInvestment CreateFall()
{
return new Fall();
}
}


Because here I have instantiated Raise and Fall classes they will be the most derived in the instantiated object class
thats inherited from fallInvestment or raiseInvestment, and the compiler will take the most derived (when overriding).

And actually here we have implemented fallInvestment and raiseInvestment (abstract classes) by the Fall and Raise
(concrete classes), inside stocks and\or bonds classes.



In my client level, the client is the class thats instantiates objects, call functions,..

In my client I want to make instances of raiseInvestment and fallInvestment by calling
investment.CreateRaise() or investment.CreateFall().

But how can I get the refrence of the decided investment?.. it can be passed as a parameter to the constructor
of the client when instantiating the client.

when i get these two instances of raiseInvestment and fallInvestment i can then call these fucntions
raiseInvestment.Plus() and fallInvestment.Minus() and I'll getthe overrided functions because they
have been the most derived.


class clientOnInvestment
{
private fallInvestment _fallInvestment;
private raiseInvestment _raiseInvestment;
private int currentBalance;

public clientOnInvestment(invsetment _investment, int currentBalance)
{
_fallInvestment = _investment.CreateFall();
_raiseInvestment = _investment.CreateRaise();
this.currentBalance = currentBalance;
}

public void doFall()
{
currentBalance = _fallInvestment.Minus(currentBalance);
}

public void doRaise()
{
currentBalance = _raiseInvestment.Plus(currentBalance);
}

public int Balance
{
get
{
return currentBalance;
}
}
}



and Finally, the Main


class Program
{
static void Main(string[] args)
{
Console.WriteLine("Welcome to Investments");

Console.WriteLine("Creating Stocks............................");

invsetment myStocks = new stocks();
clientOnInvestment myClientS = new
clientOnInvestment(myStocks, 0);//set starting balance to 0

Console.WriteLine("Current Balance = {0}", myClientS.Balance);
Console.WriteLine("Raising balance.........");

myClientS.doRaise();

Console.WriteLine("Current Balance = {0}", myClientS.Balance);
Console.WriteLine("Falling balance.........");

myClientS.doFall();

Console.WriteLine("Current Balance = {0}", myClientS.Balance);


Console.WriteLine("Creating Bonds.............................");

invsetment myBonds = new bonds();
clientOnInvestment myClientB = new
clientOnInvestment(myBonds, 0);//set starting balance to 0

Console.WriteLine("Current Balance = {0}", myClientB.Balance);
Console.WriteLine("Raising balance.........");

myClientB.doRaise();

Console.WriteLine("Current Balance = {0}", myClientB.Balance);
Console.WriteLine("Falling balance.........");

myClientB.doFall();

Console.WriteLine("Current Balance = {0}", myClientB.Balance);

}

}

2 comments:

Anonymous said...

Thank you very much for a nice code.

Islam Eldemery said...

You welcome