Monday, March 19, 2007

ACM World Programming Competition

The 2007 ACM World programming competition just wrapped up and they have released the problem set (solve it if you can). This holds a special place in my heart because at Baylor I worked for Dr. Poucher, who is the chair of the ACM contest. While most of the competitors at this level are light years ahead of me, its always fun to look around and see what they solved and how they did it. Enjoy.

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!