2009-08-20

Factory method pattern

[category]
Creational pattern.

[brief description]
This pattern provides methods to create objects which has superclass and a lot of derivatives.

[detail description]
This pattern solves the problem that other creation pattern has. (The problem is specifying the exact class of object that will be created)
This pattern separate the method to create an object so that client do not need to specify the class of object.

[expression in UML]

┌──────────┐
│ Creator │
├──────────┤
├──────────┤
│+ factoryMethod() │
│ : Product │
└──────────┘



┌───────┐ ┌──────────┐
│ Product │ │ CroncretCreator │
├───────┤ <------------ ├──────────┤
├───────┤ ├──────────┤
└───────┘ │+ factoryMethod() │
│ : Product │
└──────────┘


[sample code]

(C++)

#include <iostream>
#include <stdexcept>

// this class is interface of product
class Car
{
public:
virtual ~Car() {}
virtual void run() = 0;
};

// these are concret products
class SportCar
: public Car
{
public:
SportCar() { }
virtual ~SportCar() {}

virtual void run()
{
std::cout << "I'm a sport car." << std::endl;
std::cout << "I can run 300 km/h." << std::endl;
}
};

class LuxuryCar
: public Car
{
public:
LuxuryCar() { }
virtual ~LuxuryCar() {}

virtual void run()
{
std::cout << "I'm a luxury car." << std::endl;
std::cout << "You can feel very comfortable." << std::endl;
}
};

class NormalCar
: public Car
{
public:
NormalCar() {}
virtual ~NormalCar() {}

virtual void run()
{
std::cout << "I'm a normal car." << std::endl;
std::cout << "I'm a resonable price." << std::endl;
}
};

enum CarType
{
Sport,
Luxury,
Normal,
Other
};

class CarFactory
{
public:
static Car* createCar(CarType type)
{
switch (type) {
case Sport: return new SportCar();
case Luxury: return new LuxuryCar();
case Normal: return new NormalCar();
}
throw std::invalid_argument("We don't know how to make this car.");
}
};

int main(int, char**)
{
try {
Car* car1 = CarFactory::createCar(Sport);
Car* car2 = CarFactory::createCar(Luxury);
Car* car3 = CarFactory::createCar(Normal);

car1->run();
car2->run();
car3->run();
// the factory throws exception
Car* car4 = CarFactory::createCar(Other);
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
}

No comments:

Post a Comment