The Template Method Design Pattern

What is the Template Method design pattern?

The Template Method pattern is a pattern that defines the skeleton of an algorithm in an operation and defers some steps to client subclasses. Subclasses redefine some steps of the algorithm without changing its structure.

  • you create a group of subclasses that execute a similar group of methods.
  • Then you create an abstract class that contains a method called the Template Method. The Template Method includes a series of method calls that each subclass will have to call.
  • The subclasses can override some of the method calls — the placeholders.

The Gilded Rose Refactoring Kata

One of my previous posts dealt with the Gilded Rose Refactoring Kata. I won’t talk about how I refactored the program (if you’re curious about that, or you don’t know what the Kata is about, you can read this.)

public interface CustomisedItem {
void updateState();
}
public class AgedBrie implements CustomisedItem {

private final Item item;

//
public void updateState() {
decreaseSellByDayValueByOne();
increaseQualityByOne();
}

private void decreaseSellByDayValueByOne() {
item.sellIn -= 1;
}

private void increaseQualityByOne() {
item.quality += 1;
}
}
public class BackstagePassesItem implements CustomisedItem {

private final Item item;
// public void updateState() {
decreaseSellByDayValueByOne(); //same as above
if (sellByDayValueIsOver(10)) {
increaseQualityBy(1);
} else if (sellByDayValueIsOver(5)) {
increaseQualityBy(2);
} else if (sellByDayValueIsOver(0)) {
increaseQualityBy(3);
} else {
dropQualityToZero();
}
}
private boolean sellByDayValueIsOver(int dayNumber) {
return item.sellIn > dayNumber;
}
private void increaseQualityBy(int qualityValue) {
item.quality += qualityValue;
}
private void dropQualityToZero() {
item.quality = 0;
}
}
public class Sulfuras implements CustomisedItem {    public void updateState() {
// nothing happens
}

Using the Template Method for my Gilded Rose program

This is how I made changes to my program introducing the Template Method design pattern.

public abstract class CustomisedItem {    public final Item item;    // constructor    public final void updateState() {
item.sellIn = updatedItemSellIn();
item.quality = updatedItemQuality();

// more code implementation here common to all items
which previously was contained in the main class
GildedRose in the method updateQuality() and now
it's here
}

abstract int updatedItemSellIn(); //placeholder

abstract int updatedItemQuality(); //placeholder
}
public class AgedBrie extends CustomisedItem {// no longer
implements but extends

public AgedBrie(Item item) {
super(item); // inherits same con-
structor as parent
}

@Override // overrides 'hooks' methods
int updatedItemSellIn() { called in Template Method
return item.sellIn -= 1; implementing them
}

@Override
int updatedItemQuality() {
return item.quality += 1;
}
}
class BackstagePassesItem extends CustomisedItem {

BackstagePassesItem(Item item) {
super(item);
}

// different implementations
@Override of placeholders or hooks
int updatedItemSellIn() {
return item.sellIn -= 1;
}

@Override
int updatedItemQuality() {
if (sellByDayValueIsOver(10)) {
return qualityIncreasedBy(1);
} else if (sellByDayValueIsOver(5)) {
return qualityIncreasedBy(2);
} else if (sellByDayValueIsOver(0)) {
return qualityIncreasedBy(3);
} else {
return qualityDroppedToZero();
}
}

private boolean sellByDayValueIsOver(int dayNumber) {
return item.sellIn > dayNumber;
}

private int qualityIncreasedBy(int qualityValue) {
return item.quality += qualityValue;
}

private int qualityDroppedToZero() {
return 0;
}
}
class Sulfuras extends CustomisedItem {

Sulfuras(Item item) {
super(item);
}

@Override
int updatedItemSellIn() {
return item.sellIn; // sellIn value is not altered
}

@Override
int updatedItemQuality() {
return item.quality; // quality value is not altered
}
}

The Gilded Rose class is smaller than ever!

After all the refactoring this is how my main class GildedRose looks like:

class GildedRose {

private final CustomisedItemFactory itemFactory;
Item[] items;

public GildedRose(Item[] items) {
this.items = items;
this.itemFactory = new CustomisedItemFactory();
}

public void updateQuality() {
for (Item item : items) {
itemFactory.customiseItem(item).updateState();
}
}
}

Conclusion

It is not simple to ‘spot’ where a design pattern could suit, and sometimes it is not worthy using one of them or another. Whether a design pattern is usable or not sometimes cannot become visible until later in the implementation (as in my case with the Gilded Rose application!)

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store