Wednesday, June 12, 2013

GoF patterns: Template Method

Definition: This pattern defines the skeleton of an algorithm and let subclasses define some steps of it without changing the original algorithm structure.


Say for example, I have a service for buying tickets and I want the service to provide discounts depending on the age of the person. I want to have 2 kind of discounts, but I am sure there will be a lot more in the future. Instead of having an IF statement to do get the final price of the ticket depending on the age (and have a whole bunch of nested IF statements in the future), the ticket buying process will have the skeleton of the buying process and the step to get the final price of the ticket will be delegated to different classes. As we said, today we just have 2 different calcs of the discount but tomorrow we may have a lot more:



TicketServiceAbstract
public abstract class TicketServiceAbstract {
 
 public double buyTicket(Client client) {
  double generalTicketPrice = 50;
  double realTicketPrice = this.calculateDiscount(generalTicketPrice);
  return realTicketPrice;
 }

 protected abstract double calculateDiscount(double generalTicketPrice);

}

HighDiscountTicketService
public class HighDiscountTicketService extends TicketServiceAbstract {

 @Override
 protected double calculateDiscount(double generalTicketPrice) {
  return generalTicketPrice - 30;
 }

}

LowDiscountTicketService
public class LowDiscountTicketService extends TicketServiceAbstract {

 @Override
 protected double calculateDiscount(double generalTicketPrice) {
  return generalTicketPrice - 10;
 }

}

And this is an invocation example:

TemplateMethodPatternTest
public class TemplateMethodPatternTest {
 
 @Test
 public void templateMethodKidPatternTest() {
  
  //A new Client is created
  Client kid = new Client();
  kid.setAge(16);
  
  HighDiscountTicketService discountService = new HighDiscountTicketService();
  
  double ticketPriceForKid = discountService.buyTicket(kid);
  Assert.assertTrue(ticketPriceForKid == 20);
 }
 
 @Test
 public void templateMethodAdultPatternTest() {
  
  //A new Client is created
  Client kid = new Client();
  kid.setAge(25);
  
  LowDiscountTicketService discountService = new LowDiscountTicketService();
  
  double ticketPriceForKid = discountService.buyTicket(kid);
  Assert.assertTrue(ticketPriceForKid == 40);
 }
 
}

The Template Method pattern is similar to the Strategy pattern, in this post you can see this same example implemented with the Strategy pattern. The main difference between both patterns is that the Strategy changes its behaviour at runtime, while the Template Method changes its behaviour at compile time.

No comments:

Post a Comment