In this tutorial I end my Code Refactoring Tutorial. It was a big one and between it and my Design Patterns Video Tutorial you should be able to do most anything.

To end this tutorial, I’ll cover the Abstract Factory Pattern again to make sure you understand it. It is often considered a hard to understand pattern, but I’m sure you’ll get it after this video. The code that follows will help explain anything you miss in the video.

If you like videos like this, it helps to tell Google+

Code From the Video

The Basics of the Abstract Design Pattern
1. There is a Monster abstract class
2. The difference between the Monsters is the Objects
stored in Attack and Range
3. An interface is used to represent both options
available for Attack and Range
4. 2 classes implement that Attack & Range interfaces
5. There is a MonsterFactory interface. It represents
monsters with different Attack & Range types
6. If I want a Vampire with a MediumAttack & MediumRange
a Vampire Factory is made that assigns those classes
to the Vampire objects Attack & Range attributes
7. The only thing left is the builder that receives a string
If the String is a Vampire we pass the Vampire Factory
into the Vampire class Object.
8. The Vampire class object assigns the Attack & Range Objects
as the attributes for Attack & Range for every Vampire
Object that is created.
// This class defines attributes and capabilities
// for each monster
public abstract class Monster {
private String name;
MonsterAttackPower attackPower;
MonsterAttackRange attackRange;
abstract void makeMonster();
public void checkIfVictimIsInRange(){
System.out.println(getName() + " checks if victim is " + attackRange);
}
public void attackTheVictim(){
System.out.println(getName() + " attacks the victim for " + attackPower);
}
public String toString(){
String infoOnMonster = getName() + " attacks anything " + attackRange +
" for " + attackPower;
return infoOnMonster;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// Now since I defined these interfaces, anything
// that implements this interface can replace toString
interface MonsterAttackPower{
public String toString();
}
// These replace toString for MonsterAttackPower
class BasicAttack implements MonsterAttackPower{
public String toString(){
return "10 in damage";
}
}
class MediumAttack implements MonsterAttackPower{
public String toString(){
return "20 in damage";
}
}
// Now I do the same for MonsterAttackRange
interface MonsterAttackRange{
public String toString();
}
class BasicRange implements MonsterAttackRange{
public String toString(){
return "5 away";
}
}
class MediumRange implements MonsterAttackRange{
public String toString(){
return "10 away";
}
}
// Here I define the attributes for each monster
// and the methods that will define them
interface MonsterFactory{
public MonsterAttackPower assignAttackPower();
public MonsterAttackRange assignAttackRange();
}
// This defines the attack and range to assign to
// each Zombie created
class ZombieFactory implements MonsterFactory{
public MonsterAttackPower assignAttackPower() {
return new BasicAttack();
}
public MonsterAttackRange assignAttackRange() {
return new BasicRange();
}
}
//This defines the attack and range to assign to
//each Vampire created
class VampireFactory implements MonsterFactory{
public MonsterAttackPower assignAttackPower() {
return new MediumAttack();
}
public MonsterAttackRange assignAttackRange() {
return new MediumRange();
}
}
// A factory is sent into this class that will assign
// the right objects for attack and range to the Zombie
class Zombie extends Monster{
// The type of attack & range to assign are past
// into the constructor
MonsterFactory monsterFactory;
public Zombie(MonsterFactory monsterFactory) {
this.monsterFactory = monsterFactory;
}
void makeMonster() {
System.out.println("Making a Zombie");
// These are stored in the Monster class
attackPower = monsterFactory.assignAttackPower();
attackRange = monsterFactory.assignAttackRange();
}
}
// The same is done for the vampire
class Vampire extends Monster{
// The type of attack & range to assign are past
// into the constructor
MonsterFactory monsterFactory;
public Vampire(MonsterFactory monsterFactory) {
this.monsterFactory = monsterFactory;
}
void makeMonster() {
System.out.println("Making a Vampire");
// These are stored in the Monster class
attackPower = monsterFactory.assignAttackPower();
attackRange = monsterFactory.assignAttackRange();
}
}
// Now that I have Monsters defined, their individual attacks
// & ranges and I have a factory for making them I have to
// create a way to order them.
abstract class MonsterBuilder {
protected abstract Monster makeMonster(String typeOfMonster);
public Monster orderAMonster(String typeOfMonster){
Monster theMonster = makeMonster(typeOfMonster);
// Test out the methods for the Monster
theMonster.makeMonster();
theMonster.checkIfVictimIsInRange();
theMonster.attackTheVictim();
return theMonster;
}
}
class OrderAMonster extends MonsterBuilder{
protected Monster makeMonster(String typeOfMonster) {
Monster theMonster = null;
if(typeOfMonster.equals("Zombie")){
// Create the factory that assigns the right attributes
// to each Zombie
MonsterFactory monsterFactory = new ZombieFactory();
// Create a Zombie Monster that stores the Objects
// specific for each zombie so they can be assigned
// to this monster
theMonster = new Zombie(monsterFactory);
theMonster.setName("Zombie Bob");
} else
if(typeOfMonster.equals("Vampire")){
// Create the factory that assigns the right attributes
// to each Vampire
MonsterFactory monsterFactory = new VampireFactory();
// Create a Vampire Monster that stores the Objects
// specific for each Vampire so they can be assigned
// to this monster
theMonster = new Vampire(monsterFactory);
theMonster.setName("Vampire Paul");
}
return theMonster;
}
}
class MonsterMakerTest{
public static void main(String[] args){
// Create a way to order new monsters
MonsterBuilder monsterBuilder = new OrderAMonster();
Monster zombie = monsterBuilder.orderAMonster("Zombie");
// Makes a call to the toString method
System.out.println(zombie + "\n");
Monster vampire = monsterBuilder.orderAMonster("Vampire");
System.out.println(vampire + "\n");
}
}

Now my problem: I moved the call to the factory into an abstract final (utility) class – with a private constructor – which I use only to set up the initial game. And now I get a InvocationTargetException NullPointer error. Can Reflection only be called from concrete classes? Is there any pointer you could give, as to where to look for the error, with only this to go on?

The call to the factory is simple (and works in the Controller class):
private void setTokensFromFactory(Resources res) {
tokenSet = new ArrayList(numberTokens);
TokenFactory factory = new TokenFactory();
for (int i = 0; i < numberTokens; i++) {
tokenSet.add(factory.makeToken(i));
}
}

(And you may have noticed I am on Android – but I assume this does not matter….famous last words.

You have a NullPointerException. Don’t worry about the InvocationTargetException. This occurs when you try to access or modify an object set as null. You’ll find the line this occurs on in the error message. I hope that helps

Yeah, I know the line – it is the newInstance that is causing the problem I think. But I still cannot find a reason why it works in the main Class but not when pulled out into a utility Class. All my variables have values, the constructor has the right name etc. I think it even works for i=0 but then falls over.

Wow this really cleared things up for me. So can you explain how does singleton come into the picture for abstract classes? Which is the object that is only being created once that necessitates a Singleton?