Friday, June 7, 2013

The abstract factory pattern

Note: Code is in Java. 

According to OODesign, the intent of the abstract factory pattern is to "offer an interface for creating a family of related objects without specifying their classes."

So how does this relate to my story?

The factory

Let's imagine that when Gwen came to the village, they haven't figure out a system to plant vegetables yet. So everyone has to plant their own vegetables. In code, Todd class looks like this:
public class Todd {
 public Carrot getCarrot(){
  Carrot carrot = new Carrot();
  carrot.addWater(1);
  return carrot;
 }
 
 public Carrot getNoCrunchCarrot(){
  Carrot carrot = new Carrot();
  carrot.addWater(2);
  return carrot;
 }
}
Gwen class looks like this:
public class GwenSoupMaker {
 public Soup carrotSoup(){
  Carrot carrot = new Carrot();
  carrot.addWater(1);
  CarrotPieces carrot_pieces = cut(carrot);
  return cook(carrot_pieces);
 }
 
 private CarrotPieces cut(Carrot carrot) {
  return new CarrotPieces(carrot);
 }

 private Soup cook(CarrotPieces carrot) {
  return new Soup(carrot);
 }
}
See the duplication? It's just two line of code, so maybe it's ok. Now if one day, Alex says he found that if you add fertilizer, the carrot will grow faster. So everyone who grows carrot has to change their planting method by adding  fertilizer. Doesn't that sound like a lot of work? Couldn't I just tell Alex to grow the carrot and give it to me when I want it? That way only Alex needs to know about how to grow the carrot.public class Alex {
 
 public Carrot getCarrot(){
  return growCarrot(1);
 }
 
 public Carrot getNoCrunchCarrot(){
  return growCarrot(2);
 }
 
 private Carrot growCarrot(int gallonOfWater){
  Carrot carrot = new Carrot();
  carrot.addWater(gallonOfWater);
  carrot.addFertilizer();
  return carrot;  
 }
}
Now Todd class looks like this:
public class Todd {
 public Carrot getCarrot(){
  return Alex.getCarrot();
 }
 
 public Carrot getNoCrunchCarrot(){
  return Alex.getNoCrunchCarrot();
 }
}
Gwen looks like this:
public class GwenSoupMaker {
 
 public Soup carrotSoup(){
  Carrot carrot = Alex.getCarrot();
  CarrotPieces carrot_pieces = cut(carrot);
  return cook(carrot_pieces);
 }
 
 private CarrotPieces cut(Carrot carrot) {
  return new CarrotPieces(carrot);
 }

 private Soup cook(CarrotPieces carrot) {
  return new Soup(carrot);
 }
}
And if James wanted carrot, he doesn't need to know how to grow it either. He just asks Alex for it.
public class James {
 public Carrot getCarrot(){
  return Alex.getNoCrunchCarrot();
 }
}
In term of code, Alex is our factory. He is the only one with knowledge on how to grow carrot. If growing no crunch carrot needs 3 gallon of water, only Alex needs to know.

The abstract factory

Remember when Gwen started to do super well with her store? She had to go to Todd several times to buy zucchini. Every time she needs zucchini, she has to find Todd. But, Todd is busy man. To make it easier for customer to buy zucchini, he put up a stand in front of his house so his son or his wife can sell the zucchini when Todd is not available. That way, when Gwen needs zucchini, she goes to the stand instead of asking Todd.

In code term, that just mean Todd has an interface and Gwen just talk to the interface when she wants a zucchini. So Gwen class looks like this:
import java.util.List;

public class GwenSoupMaker {
 ZucchiniFarmer zucchiniFarmer;
 public GwenSoupMaker(ZucchiniFarmer farmer){
  zucchiniFarmer = farmer;
 }
 
 public Soup zucchiniSoup(){
  List zucchinis = zucchiniFarmer.buy(3);
  return cook(zucchinis);
 }
 
 private Soup cook(List zucchinis) {
  return new Soup(zucchinis);
 }

Todd:
import java.util.ArrayList;
import java.util.List;

public class Todd implements ZucchiniFarmer{
 public List buy(int amount) {
  List zucchinis = new ArrayList();
  for (int i = 0; i < amount; i++){
   zucchinis.add(new Zucchini(1));
  }
  return zucchinis;
 }
}
Zucchini farmers:
import java.util.List;


public interface ZucchiniFarmer {
 public List buy(int amount);
}

0 comments:

Post a Comment