Friday, October 4, 2019

Factory Method Design Pattern

Greetings!

Factory method design pattern is a creational design pattern which deals with creating objects.
Many misunderstand this pattern with simple factory helper class.

Source code for this post can be found in my github account. [source-code]

This is the definition given by GoF.
"Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory method lets a class defer instantiation to subclasses."

As in original GoF design pattern, we define an interface (abstract class) to create objects that lets the sub-class to decide how to create the object.


Let's see the actors in this design pattern.
  • Product - This is the final object we need to create. We are dealing only with abstraction here because we can have multiple types of products.
  • Factory - A class to create Product. But it doesn't directly create object. Instead it provides abstract method to create the Product. Sub classes of the Factory needs to implement that creation method.
  • ConcreteFactory - This class is responsible to create the actual Product.
  • Client - This class needs to use a Product. It uses correct Factory to construct the Product.

Working Example

To explain this, i'm going to create a hypothetical shooting game with trail and purchased versions. A player can select a weapon. How do you create TrailWeapon or PurchasedWeapon? Are you going to use multiple if else in everywhere? We do not need to do that. We can create separate factories for 2 versions.
This example needs multiple classes. Here i'll add only neccesary classes. You can get the full code from my github repository.

First, we create our Product interface which is Weapon.

package com.slmanju.patterns;

public interface Weapon {

    void fire();

    void load();

}


We can implement this to create a concrete product. Here it is Rifle.

package com.slmanju.patterns;

public class Rifle implements Weapon {

    @Override
    public void fire() {
        System.out.println("Firing with rifle.");
    }

    @Override
    public void load() {
        System.out.println("Loading bullets into rifle.");
    }

}


Then we can create our Factory, WeaponStore. Here createWeapon is our factory method.

package com.slmanju.patterns;

// factory
public abstract class WeaponStore {

    public final Weapon purchase(WeaponType weaponType) {
        Weapon weapon = createWeapon(weaponType);
        weapon.load();
        return weapon;
    }

    // factory method
    protected abstract Weapon createWeapon(WeaponType weaponType);

}


Anddd, this is jungle shooter game. Hence our concrete factory is JungleWeaponStore.

package com.slmanju.patterns;

public class JungleWeaponStore extends WeaponStore {

    @Override
    protected Weapon createWeapon(WeaponType weaponType) {
        switch (weaponType) {
            case RIFLE:
                return new Rifle();
            case SHOTGUN:
                return new Shotgun();
            default:
                return new NullWeapon();
        }
    }

}


All set. Now we can have a Warrior.

package com.slmanju.patterns;

public class Warrior {

    private Weapon weapon;

    public Warrior(Weapon weapon) {
        this.weapon = weapon;
    }

    public void fight() {
        weapon.fire();
    }

    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

}


It is time to let our Warrior to go insdie jungle to defeat enemies.

package com.slmanju.patterns;

public class ShooterGame {

    public static void main(String[] args) {
        WeaponStore weaponStore = new JungleWeaponStore();
        Weapon weapon = weaponStore.purchase(WeaponType.RIFLE);
        Warrior warrior = new Warrior(weapon);
        warrior.fight();

        weapon = weaponStore.purchase(WeaponType.SHOTGUN);
        warrior.setWeapon(weapon);
        warrior.fight();
    }

}


I hope you get the idea of factory method design pattern.

Happy coding.


No comments:

Post a Comment