-->

02/10/2011

Abstract Factory Pattern

Let me begin with a proverb, "Change is Inevitable & Good." If you are not ready to adapt to the change, you will not survive. Same case applies to our software as well.

Like many of us, I am a big time Fan of PC Games. So, i thought of interpreting the usage and implementation of a pattern on the same lines.

I love "Company of Heroes" game. It has awesome UI and whole lot of Gadgets and i had great time playing it.
Look at UI once.
If you closely observe, there are Cars, Tankers, and Flights. In fact there are different types of each kind.
Now, lets say i have Scenario, where i designed this kind of a game (Lets Assume ;))
I have to handle all these kinds of vehicles say, Tankers. Tomorrow, i got a complain that, the tankers are not efficiently attacking the Aircrafts. Now, i have to categorize Tankers into 2 different types.
1. Ground Tankers.
2. Air Tankers
Tomorrow, there may come another type. And my code should be open to implement any new kind of vehicle that may creep into scope in future.

So, in order to handle families of related and dependent objects, we use "Abstract Factory Pattern".

Coming to Game, when the user starts the game, i have to give him the following vehicles to start off.
1. Soldiers Car
2. Officers Car
3. Passenger Aircraft
4. Soldiers Aircraft
5. Land Tanker
6. Air Tanker.



Now, lets see how i will sue this creational pattern, in support of my requirement.

Step 1: First I will create a common abstract factory for supporting all kinds of vehicles in my game.
public abstract class absVehiclefactory
    {
        public string _nameOfVehicle;
        public abstract void CreatWheels();
        public abstract void CreateBody();
        public abstract void CreatePurpose();
        public void DisplayFeatures()
        {
            Console.WriteLine("Vehicle Name: "+_nameOfVehicle);
            CreateBody();
            CreatWheels();
            CreatePurpose();
        }
    }
Why abstract, why not interface. Simple, i have a common functionality "DisplayFeatures()" for all the vehicles. So, i implemented it in Base class itself. Tomorrow, if i have to change the order of display, i don't need to change each and every class. I simply modify in base class and it applies to all existing and Upcoming new classes.

Step 2: I will derive CarFactory from it. But wait, i have different cars. So lets make the Carfactpory also as a Abstract class and define what is common in between all the cars.
public abstract class CarFactory : absVehiclefactory
    {     
        public override void CreatWheels()
        {
            Console.WriteLine("Wheels Size: Small wheels");
        }
        public override void CreateBody()
        {
            Console.WriteLine("Body Size: Small Body");
        }        
    }

    public class SoldiersCar: CarFactory
    {
        public SoldiersCar(string Name)
        {
            _nameOfVehicle = Name;
        }
        public override void CreatePurpose()
        {
            Console.WriteLine("Purose: Transportation; Contains: 4 to 6 Soldiers ");
        }
    }

    public class OfficersCar : CarFactory
    {
        public OfficersCar(string Name)
        {
            _nameOfVehicle = Name;
        }
        public override void CreatePurpose()
        {
            Console.WriteLine("Purose: Transportation; Contains: 4 to 6 officers ");
        }
    }
Step 3: In the same way i have to derive "AirCraftFactory". Remember, our code should always be open to addition of one more type of aircraft, with out disturbing the client code for existing types.
public abstract class AirCraftFactory : absVehiclefactory
    {
        public override void CreatWheels()
        {
            Console.WriteLine("Wheels Size: Small Wheels");
        }
        public override void CreateBody()
        {
            Console.WriteLine("Body Size: Big Body");
        }
     
    }

    public class PassengerFlight : AirCraftFactory
    {
        public PassengerFlight(string Name)
        {
            _nameOfVehicle = Name;
        }
        public override void CreatePurpose()
        {
            Console.WriteLine("Purose: Transportation; Contains: 100 to 200 Passengers");
        }
    }
    public class SoldiersFlight : AirCraftFactory
    {
        public SoldiersFlight(string Name)
        {
            _nameOfVehicle = Name;
        }
        public override void CreatePurpose()
        {
            Console.WriteLine("Purose: Transportation; Contains: 100 to 200 Soldiers");
        }
    }

Step 4: In the same way i have to derive "TankerFactory".
public abstract class TankerFactory : absVehiclefactory
    {
        public override void CreatWheels()
        {
            Console.WriteLine("Wheels Size: Big Wheels");
        }
        public override void CreateBody()
        {
            Console.WriteLine("Body Size: Big Body");
        }
                
    }
    public class GroundTanker : TankerFactory
    {
        public GroundTanker(string Name)
        {
            _nameOfVehicle = Name;
        }
        public override void CreatePurpose()
        {
            Console.WriteLine("Purose: Attch Ground Targets; Contains: 4 to 6 Soldiers ");
        }
    }
    public class AirTanker : TankerFactory
    {
        public AirTanker(string Name)
        {
            _nameOfVehicle = Name;
        }
        public override void CreatePurpose()
        {
            Console.WriteLine("Purose: Attch Arial Targets; Contains: 4 to 6 Soldiers ");
        }
    }
Step 5: Now, look at the way we have abstracted object creation using this kind of structural implemenation of the related classes.
static void Main(string[] args)
        {
            absVehiclefactory[] Vehicles = { new SoldiersCar("SoldierCar1"), 
                                             new OfficersCar("OfficersCar1"), 
                                             new PassengerFlight("PassengerFlight1"), 
                                             new SoldiersFlight("SoldiersFlight1"), 
                                             new GroundTanker("GroundTanker1"), 
                                             new AirTanker("AirTanker1") };

            for (int i = 0; i < 6; i++)
            {
                Console.WriteLine(System.Environment.NewLine);
                Console.WriteLine("VehicleType:" + Vehicles[i].GetType().ToString() + " Vehicle No: " + (i + 1).ToString());                
                Console.WriteLine("---------------------------------------------------");
                Vehicles[i].DisplayFeatures();
                Console.WriteLine("---------------------------------------------------");
                
            }

            Console.ReadKey();
        }
Step 6: Now, lets verify the output when program starts and what are all we provided for the client.
We can even enhance the client code, by moving the object creation to another class with a creation method which accepts the type of vehicle as a parameter. noting can be refined using one single pattern. But, for now lets stick to our objective "Abstract Factory Pattern".

Finally, one small request to all readers.
"Always remember, Patterns are there for Applications, not the vice verse. Patterns are there to make complex implementation to simple. Don't try otherwise on Company projects for sake of your learning purpose."


Is it helpful for you? Kindly let me know your comments / Questions.

1 comment:

  1. excellent :-) .. thank you mic2388@gmail.com

    ReplyDelete