Template+Method

= Template Method Pattern = This is an example of the [|GoF design pattern] [|Template Method]. Here's an example taken from [|Monopoly].

Imagine the game of Monopoly. There are several kinds of (read this as classes of) squares, e.g. Go, Go To Jail, Free Parking, Real Estate. Under Real Estate there are three kinds:
 * Railroads
 * Utilities
 * Property

Here's an algorithm for what happens when the current player lands on a square: code public void landOn(Player p) { if(isOwnedBy(p) || isMortgaged) { // player does not pay itself // rent not collected if mortgaged return; }

if(isOwned) { int rent = calculateRent; p.payPlayer(this, rent); } else { // offer myself for sale to p  } } code

How do you calculate rent? Here are the three ways you calculate rent:
 * Type||Algorithm||
 * Railroad||25 * number of railroads owned by same player||
 * Utility||4 * current dice roll if only one owned or 10 * current dice roll if both are owned (contrary to popular belief, both do not have to be owned by the same player to get 10X and you do not re-roll the dice either)||
 * Property||Some base value modified by houses or hotels on the property||

Notice that the rules for landing are the same:
 * 1) If the {railroad, utility, property} is mortgaged or owned by the current player do nothing
 * 2) If the {railroad, utility, property} is owned, then (because of the first check) the current player owes money to the owner
 * 3) If the {railroad, utility, property} is not owned, then the current player has the option of buying it

The only step that varies is the calculation of the rent. So we create an abstract base class, called Real Estate, that implements the landOn method AND has one abstract method: code protected int calculateRent; code

We then write three derived classes, Railroad, Utility, Property, that each implement calculate rent: code class Railroad extends RealEstate { protected int calculateRent { Player owner = getOwner; PropertyGroup group = getPropertyGroup; int numberOwnedBySamePlayer = group.calculateNmberOwnedBy(owner); return 25 * numberOwnedBySamePlayer; } } code code class Utility extends RealEstate { protected int calculateRent { Dice dice = getDice; int currentRollValue = dice.getValue; PropertyGroup group = getPropertyGroup; int numberOwned = group.getNumberOwned;
 * Railroad**
 * Utility**

int rentMultiplier = 4; if(numberOwned == 2) { rentMultiplier = 10; }     return rentMultiplier * currentRollValue; } } code code class Property extends RealEstate { protected int calculateRent { int baseRent = getBaseRent; int houses = getNumberOfHouses; // calcualte actual rent value using baseRent and houses return calculateActualRent(baseRent, houses); } } code
 * Property**

So when a player lands on any kind of RealEstate square, the landOn method in RealEstate performs some basic checks that are true for all kinds of RealEstate types. It then polymorphically the {railroad, utility, property} to calculate the rent, if appropriate, and charges the rent to the current player.