Surprisingly, not that abstract.

The Abstract Factory contains concrete factories of a common type. Essentially, it is an interface that allows the client to create objects without knowing the underlying definitions. Since the instantiated objects the client creates are of the same type, the abstract factory is not dependent on the object, or vice versa.

Implementation

For example, lets say that we have a physical GuitarFactory where inside, there are smaller factories (SchecterFactory, GibsonFactory, etc.) that all produce guitars. Each factory creates different guitars to suit different guitarists. The guitars being created all have certain fundamental properties to them (6 strings, 24 frets, electric, etc), but are customizable to a particular factory’s needs.

In this example, it is obvious to note the participating objects in correlation to the Abstract Factory (for the sake of simplicity, lets assume the guitars are Stratocasters):

  • AbstractFactory - GuitarFactory
  • ConcreteFactories - SchecterFactory, GibsonFactory, etc.
  • AbstractProduct - Guitar
  • Concrete Product - SchecterGuitars, GibsonGuitars
// Abstract Guitar
        public abstract Guitar {
            int numStrings = 6;
            String type = "Electric";
            int numFrets = 24;

            public abstract void distort();
            public abstract void applyVibrato();
        }

        // Schecter Guitar
        public class SchecterGuitar extends Guitar {
            public void distort(){...}
            public void applyVibrato(){...}
        }

        // Gibson Guitar
         public class GibsonGuitar extends Guitar {
            public void distort(){...}
            public void applyVibrato(){...}
         }

         // GuitarFactory
        public abstract GuitarFactory {
            public abstract Guitar createGuitar();
        }

        // SchecterFactory
        public class SchecterFactory extends GuitarFactory {
            Guitar createGuitar(){
                return new SchecterGuitar();
            }
        }

        // GibsonFactory
        public class GibsonFactory extends GuitarFactory {
            Guitar createGuitar() {
                 return new GibsonGuitar();
            }
         }
         ```


        _[Note: The abstract factory is great for creating multiple objects of the same type. We could have easily extended this example to creating Les Paul guitar types, or even acoustic guitar types. That’s when you will see the Abstract Factory’s **power**.]_

        That's all fine and dandy, but you're probably wondering how to interact with the Abstract Factory.  Moving forward with the guitar example, let's say that you want to create a Schecter and Gibson guitar when you play metal and blues, respectively.
        

java public class AwesomeGuitarist {

public Guitar receiveGuitar(MusicType musicType) { GuitarFactory guitarFactory; if ( musicType.equals( "Metal" ) ) { guitarFactory = new SchecterFactory(); return guitarFactory.createGuitar(); } else if ( musicType.equals( "Blues" ) ) { guitarFactory = new GibsonFactory(); return guitarFactory.createGuitar(); } else { throw new MusicTypeNotSupportedException( "Incorrect music type!" ); } }

public void shred() { SchecterGuitar mySweetGuitar = (SchecterGuitar) receiveGuitar(new musicType( "Metal" ) ); mySweetGuitar.rockOut(); // If we had this implemented mySweetGuitar.distort(); ... }

} ```

TL:DR?

The Abstract Factory is just an interface which creates products.
The actual task for creating the products are the ConcreteProducts classes (i.e., SchecterGuitar and GibsonGuitar)