The Factory Method

Software Design Fables

Imagine code that creates a thing and then does something with the created thing.


Trade Offer

If you:

You will:


The Stubborn Duck Summoner

Chapter 1

👴 Narrator:

Once there was a summoner, a master of ducks.
His dreams were grand, but his ducks... weren't.

class StubbornDuckSummoner {
  orderCreatureToAttack(): void {
    const duck = new Duck();
    duck.attack();
  }
}

class Duck {
  attack() {
    console.log(`QUACK!`);
  }
}

🧙 Eric The Stubborn Duck Summoner:

I am the duck summoner.
I exclusively summon ducks and order them to attack.
There is no need for any other creature!
My noble ducks are simply the best!
I shall defeat the Evil King!

class EvilKing {
  /** Just exists for plot */
}

👴 Narrator:

Eric confronted the evil king with this duck.

const eric = new StubbornDuckSummoner();
const michael = new EvilKing();
eric.orderCreatureToAttack();

🦆 Duck:

I will mess you up!

🤴 Evil King:

A duck? Are you serious bro? 😒
Pathetic...🤣

🧙 Eric The Stubborn Duck Summoner:

Fate mocks me. These ducks are too weak!
I have been stubborn,
stuck in my old ways with these ducks.

I must change...

Chapter 2

👴 Narrator:

Eric was stuck with his ducks.
Not even his children could summon anything other than ducks.

🧙 Eric The Stubborn Duck Summoner:

How can I change...
Right now I only know one ability orderCreatureToAttack()
...
💡 My ability is actually doing two things...
First, It summons a creature.
Second, It orders that creature to attack my enemies.
If I dedicate creature summoning
to a separate new ability summonCreature(),
Then this would allow my children to override the creature being summoned.
And they would still have access to the orderCreatureToAttack() abilitiy.

abstract class ReformedSummoner {
  abstract summonCreature(): Creature;

  orderCreatureToAttack(): void {
    const creature = this.summonCreature();
    creature.attack();
  }
}

interface Creature {
  attack: () => void;
}

👴 Narrator:

Thus, Eric became a flexible abstract creator.
His creation formerly the duck, is an abstract creature as well.
He had gained the power of the factory method.

His children can now reap the benefits,
by overriding his factory method summonCreature()
and choosing a Creature of their liking.
They also gained orderCreatureToAttack()
through their inheritance

🥷 Bernard, son of the Duck Summoner:

My creature of choice is the Dragon

class Dragon implements Creature {
  attack() {
    console.log("BREATHES FIRE!");
  }
}

class DragonSummoner extends ReformedSummoner {
  summonCreature(): Dragon {
    return new Dragon();
  }
}

👩 Addie, Daughter of the Duck Summoner:

My creature of choice is the Phoenix

class Phoenix implements Creature {
  attack() {
    console.log("SOLAR FLARE");
  }
}
class PhoenixSummoner extends ReformedSummoner {
  summonCreature(): Phoenix {
    return new Phoenix();
  }
}

👴 Narrator:

Together, they confronted the Evil King, one last time.

const Bernard = new DragonSummoner();
const Adie = new PhoenixSummoner();
const Michael = new Enemy();

Bernard.orderCreatureToAttack();
// The sky darkens as a massive dragon emerges from the clouds...

Adie.orderCreatureToAttack();
// The air itself ignites with divine light of a great phoenix...

console.log(
  "Michael: WHAT?! IMPOSSIBLE! Ducks don't breathe fire or... whatever that was!"
);

console.log("Bernard: Father's technique...");
console.log("Adie: ...but our creatures!");

console.log(
  "Michael: NO! NO! The duck summoner's children... TOO STRONG! *dramatically disintegrates*"
);
console.log(
  "Somewhere in the afterlife, the Old Duck Summoner smiles proudly."
);

🤴 Evil King:

WHAT?! IMPOSSIBLE!
Ducks don't breathe fire or... whatever that was!

Children of the Duck Summoner

We have inherited and customized our fathers orderCreatureToAttack by overriding his new summonCreature ability. BEHOLD OUR POWER!!!