Saturday, March 3, 2007

Class Factory Design Pattern

This week I was writing some C++ code and got to use one of my favorite design patters, the "Class Factory" pattern. Lets say I have 2 ways to do something, like send a message. I can either send it in email form or snail mail. Clients will use my code to send messages but the logic stays the same for which method to use: 1) if I have an internet connection send it using email 2) if no internet, send it using snail mail.

Obviously in c++ I should create 3 classes, a base Message sender method and 2 subclasses that encapsulate the logic of either sending mail using internet or snail. But what about the logic for using the correct sending method (code that decides which subclass to create). I could require my clients to implement that logic that means that all over my software will be if-then statements creating my objects.

The other option is to create a class factory that encapsulates the logic of which subclass to create. This is shown below (obviously this is example code)



#ifndef MESSAGESENDER_H_
#define MESSAGESENDER_H_


class MessageSenderFactory;


class MessageSender
{
protected:
MessageSender();
public:

virtual ~MessageSender();

virtual void sendMessage(char* message) = 0;
};


class EmailMessageSender : MessageSender
{
private:
EmailMessageSender() {};
public:

friend class MessageSenderFactory;

virtual ~EmailMessageSender() {};

void sendMessage(char * message) {} ;

};

class SnailMailMessageSender : MessageSender
{
private:
SnailMailMessageSender() {};
public:
friend class MessageSenderFactory;

void sendMessage(char * message) {};
};


class MessageSenderFactory
{
private:
MessageSenderFactory();

public:

/**
* Creates the correct message sender.
* 1) if we have a internet connection, create a email sender
* 2) else create a snailmail sender.
*/
static MessageSender* createSender()
{
if ( HAS_INTERNET)
return new EmailMessageSender();

return new SnailMailMessageSender();
}

};

#endif /*MESSAGESENDER_H_*/

Notice that I create the constructors in my subclasses private and use the friend construct to only allow the factory to use it. This forces other code to go through the MessageSenderFactory to get new MessageSender objects, thus forcing them to use my logic.

Now, all clients have to do to send a message is:


MessageSender * sender = MessageSenderFactory::createSender();
sender->sendMessage(message);


Clean and simple. Enjoy creating class factories!

No comments: