This post implements compound pattern in <Head First Design Pattern>. The examples are based on Duck classes.
class Quackable {
public:
virtual void quack() = 0;
};
class MallardDuck : public Quackable {
public:
void quack(){
std::cout << "Quack" << std::endl;
}
};
class ReadheadDuck : public Quackable {
public:
void quack(){
std::cout << "Quack" << std::endl;
}
};
class DuckCall : public Quackable {
public:
void quack(){
std::cout << "Kwak" << std::endl;
}
};
class RubberDuck : public Quackable {
public:
void quack(){
std::cout << "Squeak" << std::endl;
}
};
First of all, the adapter pattern, we have a goose, therefore, we need a GooseAdapter:
class Goose {
public:
void honk(){
std::cout << "Honk" << std::endl;
}
};
class GooseAdapter : public Quackable {
private:
Goose* goose;
public:
GooseAdapter(Goose* goose_):goose(goose_){}
void quack(){
goose->honk();
}
~GooseAdapter(){
delete goose;
goose = NULL;
}
};
Then, the decorator pattern, we need to count the number of quack, pay attention to the static variable and how it is initialized in main function.
class QuackCounter : public Quackable {
private:
Quackable* duck;
static int numquack;
public:
QuackCounter(Quackable* duck_):duck(duck_){};
~QuackCounter(){
delete duck;
duck = NULL;
}
void quack(){
duck->quack();
numquack++;
}
static int getQuack(){
return numquack;
}
};
The main function is
#include <iostream>
#include <./duck.hpp>
int QuackCounter::numquack = 0;
int main()
{
Quackable* mallarDuck = new QuackCounter(new MallardDuck());
Quackable* readheadDuck = new QuackCounter(new ReadheadDuck());
Goose* goose = new Goose();
GooseAdapter * gduck = new GooseAdapter(goose);
Quackable* ggduck = new QuackCounter(gduck);
mallarDuck->quack();
readheadDuck->quack();
ggduck->quack();
std::cout << QuackCounter::getQuack() << std::endl;
return 0;
}
Then we want to simplify client operation by using factory method to create ducks
class DuckFacotry {
public:
virtual Quackable* createMallardDuck() = 0;
virtual Quackable* createRedheadDuck() = 0;
virtual Quackable* createDuckCall() = 0;
virtual Quackable* createRubberDuck() = 0;
};
class PureDuckFactory : public DuckFacotry {
public:
virtual Quackable* createMallardDuck(){ return new MallardDuck(); }
virtual Quackable* createRedheadDuck(){ return new RedheadDuck(); }
virtual Quackable* createDuckCall(){ return new DuckCall(); }
virtual Quackable* createRubberDuck(){ return new RubberDuck(); }
};
class CountingDuckFactory : public DuckFacotry {
public:
virtual Quackable* createMallardDuck(){
return new QuackCounter(new MallardDuck());
}
virtual Quackable* createRedheadDuck(){
return new QuackCounter(new RedheadDuck());
}
virtual Quackable* createDuckCall(){
return new QuackCounter(new DuckCall());
}
virtual Quackable* createRubberDuck(){
return new QuackCounter(new RubberDuck());
}
};
We could create ducks with/without counting ability in a uniform interface. The main function becomes
#include <iostream>
#include <./duck.hpp>
#include <./duckfactory.hpp>
int QuackCounter::numquack = 0;
int main()
{
DuckFacotry* df = new CountingDuckFactory();
Quackable* mallardDuck = df->createMallardDuck();
Quackable* readheadDuck = df->createRedheadDuck();
Goose* goose = new Goose();
GooseAdapter * gduck = new GooseAdapter(goose);
Quackable* ggduck = new QuackCounter(gduck);
mallardDuck->quack();
readheadDuck->quack();
ggduck->quack();
std::cout << QuackCounter::getQuack() << std::endl;
return 0;
}
The result is the same