I am going through the difference between Abstract Factory Pattern vs Factory Method Pattern. I understood that Factory Method is used to create one product only but Abstract Factory is about creating families of related or dependent products. But how Factory method pattern uses inheritance while the abstract factory pattern uses composition is unclear for me.
I know that this is been asked couple of times, Could any one please explain with the below code how inheritance and composition is happening?
Factory Method code
class IRose
{
public:
virtual string Color(void)=0;
};
class RedRose: public IRose
{
public:
string Color(void)
{
return "Red";
}
};
class YellowRose: public IRose
{
public:
string Color(void)
{
return "Yellow";
}
};
class IFactory
{
public:
virtual IRose* Create(string type)=0;
//The factory create method in 90% of cases will take a parameter which
//determines what kind of the object the factory will return.
};
class Factory: public IFactory
{
public:
IRose* Create(string type)
{
if ("Red" == type)
return new RedRose();
if ("Yellow" == type)
return new YellowRose();
return NULL;
}
};
int main()
{
IRose* p = NULL;
IFactory* f = NULL;
f = new Factory(); //You have to create an INSTANCE of the factory
p = f->Create("Red");
cout<<"\nColor is: "<<p->Color()<<"\n";
delete p;
p = f->Create("Yellow");
cout<<"\nColor is: "<<p->Color()<<"\n";
delete p;
return 1;
}
Abstract factory code.
class IFridge
{
public:
virtual string Run(void) = 0;
};
class FridgeSamsung : public IFridge
{
public:
string Run(void)
{
return "You are now running Samsung Fridge\n";
}
};
class FridgeWhirlpool : public IFridge
{
public:
string Run(void)
{
return "You are now running Whirlpool Fridge\n";
}
};
class IWashingMachine
{
public:
virtual string Run(void) = 0;
};
class WashingMachineSamsung : public IWashingMachine
{
public:
string Run(void)
{
return "You are now running Samsung Washing Machine\n";
}
};
class WashingMachineWhirlpool : public IWashingMachine
{
public:
string Run(void)
{
return "You are now running Whirlpool Washing Machine\n";
}
};
class IFactory
{
public:
virtual IFridge* GetFridge(void) = 0;
virtual IWashingMachine* GetWashingMachine(void) = 0;
};
class FactorySamsung : public IFactory
{
IFridge* GetFridge(void)
{
return new FridgeSamsung();
}
IWashingMachine* GetWashingMachine(void)
{
return new WashingMachineSamsung();
}
};
class FactoryWhirlpool : public IFactory
{
IFridge* GetFridge(void)
{
return new FridgeWhirlpool();
}
IWashingMachine* GetWashingMachine(void)
{
return new WashingMachineWhirlpool();
}
};
int main()
{
IFridge* fridge; //Client just knows about fridge and washingMachine.
IWashingMachine* washingMachine; //and factory. He will write operations which
IFactory* factory; //work on fridges and washingMachines.
factory = new FactorySamsung;
//This is the only place where the client
//has to make a choice.
//The rest of the code below will remain same, even
//if the factory is changed. He can change the factory and the same range
//of products but from a different factory will be returned. No need to
//change any code.
fridge = factory->GetFridge();
cout << fridge->Run();
washingMachine = factory->GetWashingMachine();
cout << washingMachine->Run();
cout << "\n";
delete factory;
factory = new FactoryWhirlpool;
//See same client code.
fridge = factory->GetFridge();
cout << fridge->Run();
washingMachine = factory->GetWashingMachine();
cout << washingMachine->Run();
cout << "\n";
delete factory;
return 1;
}
This is a revised reply after some thought.
Factory Method: Usually, createObject() is a method of the Creator object.
Abstract Factory: Usually the Factory Object is an attribute of the Creator object.
Assume now that createObject() and Factory Object belong to their respective Creator.
Factory Method: createObject() may change in sub-classes of the Creator. This happens by changing the implementation of creatObject() via inheritance.
Abstract Factory: Factory Object may also change in sub-classes of the Creator. This change however happens by replacing one Factory Object with a different Factory Object ie the Creator object is changed by composition.
In your demo creatObject() and Factory Object are external to the Creator(s) so obscuring the distinction between composition/inheritance!
Christopher Okhravi has great youTube videos on patterns.
Factory Method https://www.youtube.com/watch?v=EcFVTgRHJLM&index=4&list=PLrhzvIcii6GNjpARdnO4ueTUAVR9eMBpc
Abstract Factory https://www.youtube.com/watch?v=v-GiuMmsXj4&index=5&list=PLrhzvIcii6GNjpARdnO4ueTUAVR9eMBpc
As requested here is a version of Factory Method (in C++ this time!). If you need any assistance interpreting let me know.
class IRose
{
public:
virtual const char * Color(void) = 0;
};
class RedRose : public IRose
{
public:
const char * Color(void)
{
return "I am a Red rose";
}
};
class YellowRose : public IRose
{
public:
const char * Color(void)
{
return "I am a Yellow rose";
}
};
class RoseGarden
{
protected: class IRose* rose; // a pointer to the garden's rose
public:
virtual void createRose() { } // abstract Factory Method
public: void sayColor() {
cout << rose->Color() << '\n';
}
};
class RedRoseGarden : public RoseGarden
{
public:
void createRose()
{
this->rose = new RedRose(); // concrete factory method
}
};
class YellowRoseGarden : public RoseGarden
{
public:
void createRose()
{
this->rose = new YellowRose(); // concrete factory method
}
};
int main()
{
RoseGarden * garden = NULL;
garden = new YellowRoseGarden;
garden->createRose(); // correct factory method is chosen via inheritance
garden->sayColor();
delete garden;
garden = new RedRoseGarden;
garden->createRose(); // correct factory method is chosen via inheritance
garden->sayColor();
delete garden;
return 1;
}
Also here is a slightly modified version of Abstract Factory to better show how it is used. Just added a house object. Note I changed all your "string" objects to const char* for my compiler.
// make different types of fridges
class IFridge
{
public:
virtual const char* Run(void) = 0;
};
class FridgeSamsung : public IFridge
{
public:
const char* Run(void)
{
return "This house has a Samsung Fridge\n";
}
};
class FridgeWhirlpool : public IFridge
{
public:
const char* Run(void)
{
return "This house has a Whirlpool Fridge\n";
}
};
// make different types of washing machine
class IWashingMachine
{
public:
virtual const char* Run(void) = 0;
};
class WashingMachineSamsung : public IWashingMachine
{
public:
const char* Run(void)
{
return "This house has a Samsung Washing Machine\n";
}
};
class WashingMachineWhirlpool : public IWashingMachine
{
public:
const char* Run(void)
{
return "This house has a Whirlpool Washing Machine\n";
}
};
// make different type of factory
class IFactory
{
public:
virtual IFridge* GetFridge(void) = 0;
virtual IWashingMachine* GetWashingMachine(void) = 0;
};
class FactorySamsung : public IFactory
{
IFridge* GetFridge(void)
{
return new FridgeSamsung();
}
IWashingMachine* GetWashingMachine(void)
{
return new WashingMachineSamsung();
}
};
class FactoryWhirlpool : public IFactory
{
IFridge* GetFridge(void)
{
return new FridgeWhirlpool();
}
IWashingMachine* GetWashingMachine(void)
{
return new WashingMachineWhirlpool();
}
};
// Make a house object that has a fridge and a washing machine
class House
{
private:
class IWashingMachine * washingMachine;
class IFridge * fridge;
public:
House(IFactory * houseFactory) {
washingMachine = houseFactory->GetWashingMachine();
fridge = houseFactory->GetFridge();
}
void showAppliances() {
cout << washingMachine->Run();
cout << fridge->Run();
}
};
int main()
{
class IFactory * factory;
class House * house;
// make a samsung house
factory = new FactorySamsung;
house = new House(factory); // passing the factory by injection
house->showAppliances(); // now we have a Samsung house
cout << '\n';
// clean up
delete house;
delete factory;
// make a whirlpool house
factory = new FactoryWhirlpool;
house = new House(factory); // passing the factory by injection
house->showAppliances(); // now we have a WHilepool house
cout << '\n';
// clean up
delete house;
delete factory;
return 1;
}