Abstract Factory in C++
Why read if you can watch?
Watch Abstract Factory's video tutorialBefore and after
Trying to maintain portability across multiple "platforms" routinely requires lots of preprocessor "case" statements. The Factory pattern suggests defining a creation services interface in a Factory base class, and implementing each "platform" in a separate Factory derived class.
BEFORE - The client creates "product" objects directly, and must embed all possible platform permutations in nasty looking code.
#define MOTIF
class Widget {
public:
virtual void draw() = 0;
};
class MotifButton : public Widget {
public:
void draw() { cout << "MotifButton\n"; }
};
class MotifMenu : public Widget {
public:
void draw() { cout << "MotifMenu\n"; }
};
class WindowsButton : public Widget {
public:
void draw() { cout << "WindowsButton\n"; }
};
class WindowsMenu : public Widget {
public:
void draw() { cout << "WindowsMenu\n"; }
};
void display_window_one() {
#ifdef MOTIF
Widget* w[] = { new MotifButton,
new MotifMenu };
#else // WINDOWS
Widget* w[] = { new WindowsButton,
new WindowsMenu };
#endif
w[0]->draw(); w[1]->draw();
}
void display_window_two() {
#ifdef MOTIF
Widget* w[] = { new MotifMenu,
new MotifButton };
#else // WINDOWS
Widget* w[] = { new WindowsMenu,
new WindowsButton };
#endif
w[0]->draw(); w[1]->draw();
}
int main( void ) {
#ifdef MOTIF
Widget* w = new MotifButton;
#else // WINDOWS
Widget* w = new WindowsButton;
#endif
w->draw();
display_window_one();
display_window_two();
}
MotifButton
MotifButton
MotifMenu
MotifMenu
MotifButton
AFTER - The client: creates a platform- specific "factory" object, is careful to eschew use of "new", and delegates all creation requests to the factory.
#define WINDOWS
class Widget {
public:
virtual void draw() = 0;
};
class MotifButton : public Widget {
public:
void draw() { cout << "MotifButton\n"; }
};
class MotifMenu : public Widget {
public:
void draw() { cout << "MotifMenu\n"; }
};
class WindowsButton : public Widget {
public:
void draw() { cout << "WindowsButton\n"; }
};
class WindowsMenu : public Widget {
public:
void draw() { cout << "WindowsMenu\n"; }
};
class Factory {
public:
virtual Widget* create_button() = 0;
virtual Widget* create_menu() = 0;
};
class MotifFactory : public Factory {
public:
Widget* create_button() {
return new MotifButton; }
Widget* create_menu() {
return new MotifMenu; }
};
class WindowsFactory : public Factory {
public:
Widget* create_button() {
return new WindowsButton; }
Widget* create_menu() {
return new WindowsMenu; }
};
Factory* factory;
void display_window_one() {
Widget* w[] = { factory->create_button(),
factory->create_menu() };
w[0]->draw(); w[1]->draw();
}
void display_window_two() {
Widget* w[] = { factory->create_menu(),
factory->create_button() };
w[0]->draw(); w[1]->draw();
}
int main( void ) {
#ifdef MOTIF
factory = new MotifFactory;
#else // WINDOWS
factory = new WindowsFactory;
#endif
Widget* w = factory->create_button();
w->draw();
display_window_one();
display_window_two();
}
WindowsButton
WindowsButton
WindowsMenu
WindowsMenu
WindowsButton
