Reputation: 20312
Taken from wikipedia:
In object-oriented computer programming, a factory is an object for creating other objects. It is an abstraction of a constructor, and can be used to implement various allocation schemes.
Could anyone please explain when a factory class is required or beneficial?
I am currently working on a project where I have a class and use the constructor to initialize an object (duh!) but it can fail and not initialize at all. I have a Success property to check if it was created properly. Is this a good example for when a factory class should be implemented? This way the Create() method can return null and I can get rid of the Success property. Do I have the right idea?
Upvotes: 2
Views: 325
Reputation: 106096
A factory's purpose is to determine, at run-time and hence potentially and often with data unavailable when the program was compiled, which of many class
es, all derived from a specific class with virtual
methods, should capture that data for your program.
The point is that polymorphic language features allow you to work with different types of data (sharing a common base class), invoking the type-appropriate behaviours. To benefit from this, you need to have objects of different derived types. When learning about this in a Comp Sci course, you probably hard-code creation of a few of each of the Derived types and play with them through pointers to the base class. In complex real-world problems, rather than hard-coding creation it is often driven off data arriving from the programs input, such as database tables, files, and sockets. Depending on what exactly you see at each point, you want to create an appropriately-typed object to represent it, but you'll probably need to keep a record of it using a compile-time known type: the pointer to base class. Then, not only can you preform the operations that the base class promises - some of which may involve dynamic dispatch to the derived class's implementation, but you can also - if necessary - determine exactly what the real type of the data is and invoke actions accordingly.
For example, say you read the following file, which shows how you've collected different types of data for each:
elephant name Tip-Toes partner Mega
mule name Dare-You mane_length 132
You have the following class heirarchy to represent these:
struct Animal
{
Animal(const std::string& name) : name_(name) { }
virtual void eat_from(Supplies&) = 0; // animals must do in their own way...
virtual bool can_jump() { return false; } // some animals might, assume not...
std::string name_;
};
struct Elephant : Animal
{
Elephant(const std::string& name, const std::string& partner)
: Animal(name), partner_(partner)
{ }
std::string partner_;
virtual void eat_from(Supplies&) { supplies.consume(Tofu, 10 * kg); }
void swing_trunk(); // something specific to elephants
};
struct Mule : Animal
{
Mule(const std::string& name, double kgs) : Animal(name), kilograms_(kgs) { }
double kilograms_;
virtual void eat_from(Supplies&) { supplies.consume(Grass, 2 * kg); }
virtual bool can_jump() { return true; }
};
The factory method's job is to distinguish elephant from mule and return a new object of the appropriate type (derived from - but not simply - Animal):
Animal* factory(std::istringstream& input)
{
std::string what, name;
if (input >> what && input >> name)
{
if (what == "elephant")
{
std::string partner;
if (input >> partner)
return new Elephant(name, partner);
}
else if (what == "mule")
{
double mane_length;
if (input >> mane_length)
return new Mule(name, mane_length);
}
}
// can only reach here on unparsable input...
throw runtime_error("can't parse input");
}
You can then store Animal*s and perform operations on them:
std::vector<Animal*> animals;
// we expect 30 animals...
for (int i = 0; i < 30; ++i) animals.push_back(factory(std::cin));
// do things to each animal...
for (int i = 0; i < 30; ++i)
{
Animal* p_unknown = animals[i];
std::cout << p_unknown->name() << '\n';
if (Elephant* p = dynamic_cast<Elephant*>(p_unknown))
p->swing_trunk();
}
Returning to your question:
I am currently working on a project where I have a class and use the constructor to initialize an object (duh!) but it can fail and not initialize at all. I have a Success property to check if it was created properly. Is this a good example for when a factory class should be implemented? This way the Create() method can return null and I can get rid of the Success property. Do I have the right idea?
No, not a situation where a factory is useful, as there's still only one type involved. Just stick with what you've got (in an OO sense), but you could choose to throw an exception, abort the program etc. rather than set a flag that the called may or may not bother to check.
Upvotes: 3
Reputation: 7792
I will try a simple answer :)
From Wikipedia.
Use the factory pattern when:
So I think you don't 'need' a factory in your particular case. But I'd say having one does not hurt.
A common use for factories would be if you want to return an interface and hide the implementing class.
For instance:
public final class LoginFactory {
private final static Map<SomeEnum, LoginInterface> IMPLEMENTERS = new HashMap<SomeEnum, LoginInterface>();
static {
IMPLEMENTERS.put(SomeEnum.QUICK, new QuickerLoginImpl());
IMPLEMENTERS.put(SomeEnum.SECURE, new SecureLoginImpl());
}
public static LoginInterface getLoginImpl(SomeEnum type) { // my naming is bad ...
return IMPLEMENTERS.get(type);
}
}
This way you can change your SecureLoginImpl
to MoreSecureLoginImpl
for example without the user of your API even noticing.
You might also want to have a look at this wiki page Abstract Factory pattern.
Upvotes: 1
Reputation: 17027
My opinion on the Factory pattern has always been somewhat different, but I'll give it anyway.
A Factory is for creating a set of related types. Related does not mean that they necessarily implement the same interface(s) exactly. Related means that if you have one type you need to instantiate, and then you need to create another object and the concrete (implementation) type of the second object depends on the concrete type of the first object, you need a Factory.
A Factory that only creates one type of object (there is no "relatedness") is not a Factory but more like a Strategy.
My above definitions imply that Factory isn't used or needed as much as you would think.
And for objects that fail to initialize, I recommend the fail-fast approach by throwing an exception instead of relying on a status field.
Upvotes: 1
Reputation: 20721
The textbook example for a Factory situation is when you have an interface and several implementations, but you don't want to expose the implementations. You implement a factory (method or class) that produces instances of different implementations based on the parameters you pass it; however, since it returns them by the interface type, the caller will not be burdened with implementation details.
Real-world example: Suppose you have defined an interface for a stream reader, and implementations to read from a local file, a network resource, and stdin. You then write a factory method that takes a single parameter (the URI), and returns a suitable reader. The caller doesn't need to know about implementation details. The best part is, when you decide you want to support another input method, say, data: URIs, you just add another implementation and add it to the factory - you won't need to change anything in the calling code.
Upvotes: 7