Abstract Factory design pattern

The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes.In normal usage, the client software creates a concrete implementation of the abstract factory and then uses the generic interface of the factory to create the concrete objects that are part of the theme. The client doesn't know (or care) which concrete objects it gets from each of these internal factories, since it uses only the generic interfaces of their products. This pattern separates the details of implementation of a set of objects from their general usage and relies on object composition, as object creation is implemented in methods exposed in the factory interface.

[Wikipedia]

Intro

In this example we will create an Abstract factory in order to generate villainFactory and heroFactory. Those factories will generate heros and villains according to this design pattern. 

AbstractFactory


public abstract class AbstractFactory {

    /*
    Abstract class for Villain and Hero
     */

    abstract Villain getVillain(String s);
    abstract Hero getHero(String s);

}

FactoryGenerator


public class FactoryGenerator {
    /*
    generates new factory
    we can generate Villain factory or Hero factory
     */

    public static AbstractFactory factory(String s){
        switch (s){
            case "hero":
                return new HeroFactory();
            case "villain":
                return new VillainFactory();
            default: return null;
        }
    }
}

Hero


    public interface Hero {
        void specialAbility();
}

Villain


    public interface Villain {
    void specialAbility();
    void useAbility();
}

HeroFactory


   public class HeroFactory extends AbstractFactory {
    @Override
    Villain getVillain(String s) {
        return null;
    }

    //  create a hero by encapsulating hero creation
    Hero getHero(String heroType) {
        switch (heroType){
            case "cop":
                return new Cop();   //creates new cop
            case "judge":
                return new Judge();    //creates new judge
            default:
                return null;
        }
    }
}   
    

VillainFactory


public class VillainFactory extends  AbstractFactory {

    //create a villain by encapsulating villain creation
    public Villain getVillain(String villainType){
        switch (villainType){
            case "warrior":
                return new Warrior();   //creates new warrior
            case "sniper":
                return new Sniper();    //creates new sniper
            case "magician":
                return new Magician();  //creates new magician
            default:
                return null;
        }
    }

    @Override
    Hero getHero(String s) {
        return null;
    }
}

Warrior

   
public class Warrior implements Villain {

    @Override
    public void specialAbility() {
        System.out.println("I can use my special sword!");
    }

    @Override
    public void useAbility() {
        System.out.println("feel my sword power!");

    }
}

Magician


    public class Magician implements Villain {

    @Override
    public void specialAbility() {
        System.out.println("I can use magic!");
    }

    @Override
    public void useAbility() {
        System.out.println("taste the magic!");
    }
}

Sniper


    public class Sniper implements Villain {

    @Override
    public void specialAbility() {
        System.out.println("I can use my sniper rifle!");
    }

    @Override
    public void useAbility() {
        System.out.println("sniper rifle shot!");
    }
}

Judge


    
public class Judge implements Hero {
    @Override
    public void specialAbility() {
        System.out.println("I got my hammer!");
    }
}

Cop


  public class Cop implements Hero {
    @Override
    public void specialAbility() {
        System.out.println("I will use handcuffing!");
    }
}
     

Main


  public class Main {
    /*
    We will create an Abstract factory in order to generate villainFactory and heroFactory. 
    those factories will generate heros and villains.
    */
    public static void main(String[] args) {
        //creates new Villain factory
        AbstractFactory villainGenerator= FactoryGenerator.factory("villain");

        //create a Warrior
        Villain villain1 = villainGenerator.getVillain("warrior");
        System.out.println("Warrior was created!");

        //call specialAbility method
        villain1.specialAbility();
        villain1.useAbility();
        System.out.println();

        //create a Sniper
        Villain villain2 = villainGenerator.getVillain("sniper");
        System.out.println("Sniper was created!");

        //call specialAbility method
        villain2.specialAbility();
        villain2.useAbility();
        System.out.println();

        //create a Magician
        Villain villain3 = villainGenerator.getVillain("magician");
        System.out.println("Magician was created!");

        //call specialAbility method
        villain3.specialAbility();
        villain3.useAbility();
        System.out.println();

        //creates new Hero factory
        AbstractFactory heroGenerator= FactoryGenerator.factory("hero");

        //create a Cop
        Hero hero1 = heroGenerator.getHero("cop");
        System.out.println("Cop was created!");

        //call specialAbility method
        hero1.specialAbility();
        System.out.println();

        //create a Judge
        Hero hero2 = heroGenerator.getHero("judge");
        System.out.println("Judge was created!");

        //call specialAbility method
        hero2.specialAbility();
    }
}
     

Running Example


Warrior was created!
I can use my special sword!
feel my sword power!

Sniper was created!
I can use my sniper rifle!
sniper rifle shot!

Magician was created!
I can use magic!
taste the magic!

Cop was created!
I will use handcuffing!

Judge was created!
I got my hammer!