The Factory Design Pattern Tutorial and Example



This is a factory pattern tutorial for those interested in software design patterns. In software programming, a factory pattern lets you create specific objects customized with whatever values you desire but without the effort of crafting many lines of code each time you need a new object. You code the factory once then reuse it.

It's similar to being at a fast food restaurant and saying "I'll have a cheeseburger" or "I'll have a veggie burger." The cashier send in orders and the cooks use a standard recipe to produce the same burgers each time. The blueprint for a cheeseburger is: buns, beef patty, lettuce, tomato, onion, melted cheese, ketchup, and mustard. Similarly, for a veggie burger: buns, tofu patty, lettuce, tomato, and mayonnaise.

In essence, you don't have to worry about how it's made and you know what you're going to get. Soon you'll have delicious food in your hands. If you're hungry later, you can find another restaurant from the same chain and order the same burger again.

Well in software, the general concept described above is abstraction.  It enforces data and logic encapsulation (a tenet of object oriented programming) in addition to standardizing the data running in your application. The net effect is a reduction in solution sprawl and cloning of code, and an increase in simplicity and readability. If you wish to modify your code you'll only have to deal with a few precise lines. Compare this to dealing with sets of lines pieced together in complex ways in various locations. Reusing the burger example, imagine if you had to make your own burger yourself, each time, at different restaurants, with whatever tools and ingredients available, but always trying to produce the same result!

Examples of real applications of the factory pattern might be to:
  • Create instances of different types of 3D objects or characters in games.
  • Synthesize text based on criteria.
  • Convert a stream of network data representing messages into consumable objects with member functions (producer-consumer pattern).
Let's create a factory pattern example.  We'll model that fast food restaurant and we'll use pseudo-code while noting this example applies to Java, C#, C++, and any other object oriented programming language that supports polymorphism.

// First let's define a restaurant customer ...
Class Customer
{
  string tellOrder();
  float  payMoney();
  void   receive(Food f);
  void   eat();
  void   leave();
}

 
// And the cashiers working the front counter ...
Class Cashier
{
  void   listen(string spokenOrder)
  string createOrder();
  void   retrieve(Food f);
  Food   giveFood();
}


// This is the base class for all foods
// created at the restaurant.
Class Food
{
  Food();
}

 
// A CheeseBurger "is a" Food
Class CheeseBurger is Food
{
  CheeseBurger()
  {
    // Create: grill beef patty, add bun + lettuce

    //   + tomato + onion + cheese + ketchup + mustard.
  }
}


// A VeggieBurger "is a" Food
Class VeggieBurger is Food
{
  VeggieBurger()
  {
    // Create: grill tofu patty, add bun + lettuce

    //   + tomato + mayonnaise.
  }
}


// FrenchFries "is a" Food
Class FrenchFries is Food
{
  FrenchFries()
  {
    // Create: potato sticks + deep fry + add salt.
  }
} 


// Now let's define the restaurant cook,
// who represents the factory pattern.
Class Cook
{
  /* The method below is called a "Factory Method." No Cook object need be instantiated to call it. It's just a static call. The return type is the base class Food. All objects created and returned 'are' Food no matter what specific type they are. Other function calls in the code expect Food items and so the Customer's receive(Food f) and Cashier's retrieve(Food f) can work with any type of food created. The factory method thus creates polymorphic objects and its clients consume them. */

 
  Static Food CreateFood(string order)
  {
    if( string == "Cheese Burger" ) then

      return CheeseBurger;

    else if( string == "Veggie Burger" ) then

      return VeggieBurger;

    else if( string == "French Fries" ) then

      return FrenchFries;

    else
      // You should never be here. The Cashier

      // should have told the customer this item
      // is not on the menu.
      return Null;
    end if
  }
}


// Putting it all together ...
Main_Function()
{
  Customer customer;

  Cashier cashier;

  cashier.listen( customer.tellOrder() );

  cashier.acceptPayment( customer.payMoney() );

  string theOrder = cashier.createOrder();

  Food preparedFood = Cook::CreateFood( theOrder );

  cashier.retrieve( preparedFood );

  customer.receiveFood( cashier.giveFood() );

  customer.eat();

  customer.leave();
}


In real applications, the factory class is often named something like "GraphicsFactory" or "TextFactory." A common approach is also to pass-in integers or enumeration values explicitly defining what objects can be created. The if-else block can also be (and often is) a switch statement instead. In languages like C++, you would be working with object pointers, and so the factory class would look something like this:

class Cook
{
  public:

    enum FoodType
    {
      CHEESE_BURGER = 0,
      VEGGIE_BURGER,
      FRENCH_FRIES
    };

    static Food* CreateFood(const FoodType &f)
    {
      Food *food = 0;

      if( CHEESE_BURGER == f )
      {
        food = new CheeseBurger();
      }
      else if( VEGGIE_BURGER == f ) then
      {
        food = new VeggieBurger();
      }
      else if( FRENCH_FRIES == f ) then
      {
        food = new FrenchFries();
      }
      else
      {
 
        // You should never be here. The Cashier
        // should have told the customer this item
        // is not on the menu.
        food = 0;
      }

      Return food;
    }

  Private:
 

    // Hidden constructors, destructor,
    // and assignment operator ... never to be used.
    Cook();


    Cook(const Cook &c); // copy constructor

 
    ~Cook(){};


    // assignment operator.
    Cook& operator=(const Cook &c);
};

In C++ the cashier and customer method interfaces would also deal with pointers. Don't forget to delete the objects, else you'll get memory leaks! One approach there is to use std::auto_ptr's.

  void myFunction()
 {
    std::auto_ptr<Food> foodPtr = 

        Cook::CreateFood(CHEESE_BURGER);

    // do something with foodPtr.
  }


// Memory allocated by CreateFood() is deleted
// when foodPtr goes out of scope.

The alternative to using one Create() method with an input parameter defining what to create is a family of methods with no parameters at all:

Food Cook::CreateCheeseBurger();
Food Cook::VeggieBurgerBurger();
Food Cook::CreateFries();


The choice is yours ... whatever is best for your application.

And finally, you can also having a family of factories all inheriting from a base class. This is called the Abstract Factory pattern. For example:

// Base class for all Cooks
Class Cook
{
}

// This cook makes unhealthy but yummy greasy food.
GreasySpoonCook is Cook
{
}

// This cook makes cheese burgers, veggie
// burgers, and fries using healthier ingredients.
HealthyCook is Cook
{
}

// This Cook sings while cooking.
SingingCook is Cook
{
}

Depending on the restaurant type, a "greasy spoon" factory (Cook) can be used, or maybe a healthy food factory, or a singing factory if the restaurant wants to entertain its customers or annoy its cashiers. The same food items are ordered, but intrinsically they will be different (GreasyBurger, HealthyBurger, JustABurger). They will all still be a sub-type of the Food class.

And there you have it, that was the factory pattern. Good luck!

Permalink:
http://coderomp.blogspot.com/2013/01/factory-design-pattern-example.html

Similar Articles:

Post a Comment

What are your thoughts?