#include <iostream>
#include <memory>
// tags
enum genre_enum{ROCK, POP, REGGAE, INVALID};
/* Base CLass - Pure Abstract */
class Music{
public:
virtual void song() = 0;
};
/* Derived class Rock from Music */
class Rock : public Music{
public:
Rock(){};
virtual ~Rock(){};
virtual void
song(){
std::cout << "Nirvana: Smells like teen spirit\n";
}
};
/* Derived class Rock from Music */
class Pop : public Music{
public:
Pop(){};
virtual ~Pop(){};
virtual void
song(){
std::cout << "Michael Jackson: Billy Jeans \n";
}
};
/* Derived class Reggae from Music */
class Reggae : public Music{
public:
Reggae(){};
virtual ~Reggae(){};
virtual void
song(){
std::cout << "Bob Marley: No woman, no cry \n";
}
};
/* Design Pattern: Factory method implementation class*/
class MusicFactory{
public:
/* Factory Method */
virtual std::unique_ptr<Music> getMusic(genre_enum genre) = 0;
};
class Factory : public MusicFactory{
public:
virtual std::unique_ptr<Music>
getMusic(genre_enum genre){
std::unique_ptr<Music> music(nullptr);
switch(genre){
case ROCK:
music = std::make_unique<Rock>();
break;
case POP:
music = std::make_unique<Pop>();
break;
case REGGAE:
music = std::make_unique<Reggae>();
case INVALID:
break;
}
return music;
}
};
/*
There can be multiple Factory class each designed based on requirement. Example AsianMusicFactory, EuropeanMusicFactory classes
They all define the "getMusic(genre_enum genre)" method (aka factory method) in their class definition.
*/
int
main(){
std::unique_ptr<MusicFactory> musicFactory( std::make_unique<Factory>() );
//std::unique_ptr<Music> music = musicFactory->getMusic(ROCK);
auto music = musicFactory->getMusic(ROCK);
if(music)
music->song();
else
std::cout << "Wrong Selection.\n";
music = musicFactory->getMusic(REGGAE);
if(music)
music->song();
else
std::cout << "Wrong Selection.\n";
music = musicFactory->getMusic(INVALID);
if(music)
music->song();
else
std::cout << "Wrong Selection.\n";
return 0;
}
/* OUTPUT:
Nirvana: Smells like teen spirit
Bob Marley: No woman, no cry
Wrong Selection.
We made three types of Music without knowing their specific class names. We defer the instantiation
to Factory class to create the three objects (of Music class).
In essence, a factory method is a normal method which returns an instance of a class (in the example,
it is an object of Music class).
*/
/* Reference
[1] http://codereview.stackexchange.com/questions/56924/factory-design-pattern-with-music-classes
Compile in linux terminal:
clang++ -std=c++14 -stdlib=libc++ FactoryMethodDP.cpp
*/