Much like the Factory Pattern, discussed earlier, the Abstract Factory Pattern let's us create concrete objects based on information that we do not know until run time. However, the Abstract Factory pattern let's us group like factory classes together. In the example below we group a factory for creating military vehicles and a factory for creating civilian vehicles together and then we decide what "kind of" vehicles to create based on the information which we will get at run time.

The UML diagram for this pattern looks something like this:-

And below there is an implementation in C#

using System;
using System.Collections.Generic;
using System.Text;

namespace AbstractFactoryPattern
{
    //Create an enum to define whether or not we are at war
    public enum WarStatus
    {
        AtWar,
        NotAtWar
    }

    //Create an enum to define ground type
    public enum GroundType
    {
        OnRoad,
        OffRoad
    }

    //Create Factory hierarchy

    public abstract class VehicleFactory
    {
        public abstract Vehicle GetVehicle(GroundType gt);
    }
    public class MilitaryVehicleFactory : VehicleFactory
    {
        public override Vehicle GetVehicle(GroundType gt)
        {
            Vehicle v = null;
            switch (gt)
            {
                case GroundType.OffRoad :
                    v = new MilitaryTrackedVehicle();
                    break;
                case GroundType.OnRoad :
                    v = new MilitaryWheeledVehicle();
                    break;
            }
            return v;
        } 

    }
    public class CivilianVehicleFactory : VehicleFactory
    {
        public override Vehicle GetVehicle(GroundType gt)
        {
            Vehicle v = null;
            switch (gt)
            {
                case GroundType.OffRoad :
                    v = new CivilianTrackedVehicle();
                    break;
                case GroundType.OnRoad :
                    v = new CivilianWheeledVehicle();
                    break;
            }
            return v;
        }
    }

    //Create Vehicle hierarchy

    public abstract class Vehicle
    {
        public abstract void Drive();
        public abstract void FireWeapon();
    }
    public class CivilianTrackedVehicle : Vehicle
    {
        public override void Drive()
        {
            Console.WriteLine(
                "Civilian vehicle driving off road!");
        }
        public override void FireWeapon()
        {
            Console.WriteLine(
                "Civilian tracked vehicle is unarmed!");
        }
    }
    public class CivilianWheeledVehicle : Vehicle
    {
        public override void Drive()
        {
            Console.WriteLine(
                "Civilian vehicle driving on the road!");
        }
        public override void FireWeapon()
        {
            Console.WriteLine(
                "Civilian wheeled vehicle is unarmed!");
        }
    }
    public class MilitaryTrackedVehicle : Vehicle
    {
        public override void Drive()
        {
            Console.WriteLine(
                "Military vehicle driving off road!");
        }
        public override void FireWeapon()
        {
            Console.WriteLine(
                "Military tracked vehicle firing!");
        }
    }
    public class MilitaryWheeledVehicle : Vehicle
    {
        public override void Drive()
        {
            Console.WriteLine(
                "Military vehicle driving on the road!");
        }
        public override void FireWeapon()
        {
            Console.WriteLine(
                "Military wheeled vehicle firing!");
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            //Test the factories

            //We're at war, let's create vehicles
            MilitaryVehicleFactory mvf = 
                new MilitaryVehicleFactory();
            Vehicle mv1 = 
                mvf.GetVehicle(GroundType.OffRoad);
            Vehicle mv2 = 
                mvf.GetVehicle(GroundType.OnRoad);

            //The war's over, lets create more vehicles
            CivilianVehicleFactory cvf = 
                new CivilianVehicleFactory();
            Vehicle cv1 = 
                cvf.GetVehicle(GroundType.OffRoad);
            Vehicle cv2 = c
            vf.GetVehicle(GroundType.OnRoad);

            //Let's make our vehicles work!
            Vehicle[] vehicles = { mv1, mv2, cv1, cv2 };
            foreach (Vehicle v in vehicles)
            {
                v.Drive();
                v.FireWeapon();
            }
        }
    }
}

The output from this implementation looks like this:-