Well as it’s name suggests , the factory design pattern is a fancy and efficient method for creating objects, some use case of it is if your application is going to change the process of object creation , or you want to hide the process of object creation “the new keyword basically ” .
this particular pattern introduces the concept of “loose coupling” between classes , this is done by programming using abstract entities, hiding the concrete implementation to make the application more flexible and less fragile .
no more talk , let’s get to the implementation .
first let’s describe a problem :
we are designing a video game , and at some point we need to create a lot of different types of enemies for our hero so to facilitate the process of enemies creation , we create an abstract Enemy class and then specefic enemy classes , then we create a “Factory” class to generate the objects , something kind of like this :
First of all we create an enum, to keep track of enemy types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public enum EnemyType { | |
BIGENEMY, | |
SMALLENEMY, | |
SMARTENEMY | |
} |
then we create the Abstract Enemy class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class Enemy { | |
private EnemyType enemyType; | |
public Enemy(EnemyType enemyType) { | |
this.enemyType = enemyType; | |
} | |
// this is for subclasses to implement | |
protected abstract void construct(); | |
public EnemyType getType() { | |
return enemyType; | |
} | |
public void setType(EnemyType enemyType) { | |
this.enemyType = enemyType; | |
} | |
} |
and then we start implementing the subclasses of our Enemy class :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SmartEnemy extends Enemy { | |
public SmartEnemy() { | |
super(EnemyType.SMARTENEMY); | |
construct(); | |
} | |
// you can do all kinds of stuff here i'm | |
// just keeping it simple and only printing a message to the console | |
@Override | |
protected void construct() { | |
System.out.println("creating the smart enemy object "); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SmallEnemy extends Enemy { | |
public SmallEnemy() { | |
super(EnemyType.SMALLENEMY); | |
construct(); | |
} | |
@Override | |
protected void construct() { | |
System.out.println("creating the smaall enemy object "); | |
} | |
} |
the BigEnemy class is just the same as the others .
now to create the Factory objects, in our case the object creation will depend on it’s Type
if a SmallEnemy type passed to the factory it will create a new SmallEnemy Object .
Something that looks a bit like this
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class EnemyFactory { | |
public static Enemy create(EnemyType enemyType) { | |
Enemy enemy = null; | |
switch (enemyType) { | |
case SMALLENEMY: | |
enemy = new SmallEnemy(); | |
break; | |
case SMARTENEMY: | |
enemy = new SmartEnemy(); | |
break; | |
default: | |
// throw some kind of exception | |
throw new RuntimeException("the given enemy type does not existe "); | |
} | |
return enemy; | |
} | |
} |
testing it is quite simple . you can add other kind of enemy types easily now .
here are some other benefits of the factory design pattern (which i didn’t know , i googled it while writing this blog-post :p ) :
- Allows you to hide implementation of an application (the core interfaces that make up your application)
- Allows you to easily test the seam of an application (that is to mock/stub) certain parts of your application so you can build and test the other parts
there you have it folks . the factory design pattern . Happy Coding …