Reputation: 21
Is below implementation of Abstract Factory Design Pattern is correct?
#include<iostream>
using namespace std;
//Abstract Product A
class Document
{
public:
virtual void createDocument() = 0;
};
class Word: public Document
{
public :
virtual void createDocument()
{
cout<<"Document Word is created"<<endl;
}
};
class Excel : public Document
{
public :
virtual void createDocument()
{
cout<<"Document Excel is created"<<endl;
}
};
//Abstract Product B
class VideoFile
{
public:
virtual void createVideoFile() = 0;
};
class VLC : public VideoFile
{
public :
virtual void createVideoFile()
{
cout<<"VideoFile VLC is created"<<endl;
}
};
class AVI : public VideoFile
{
public :
virtual void createVideoFile()
{
cout<<"VideoFile AVI is created"<<endl;
}
};
//////////////////////////////////////////////////////////////////////
class AbstractFactory
{
public:
virtual Document* createDocFiles(string fileType) = 0;
virtual VideoFile* createVideoFiles(string fileType) = 0;
};
class ConcreteFactoryA : public AbstractFactory
{
public:
virtual Document* createDocFiles(string fileType)
{
if(fileType == "Word")
return new Word();
if(fileType == "Excel")
return new Excel();
}
virtual VideoFile* createVideoFiles(string fileType)
{
if(fileType == "VLC")
return new VLC();
if(fileType == "AVI")
return new AVI();
}
};
class ConcreteFactoryB : public AbstractFactory
{
public:
virtual Document* createDocFiles(string fileType)
{
if(fileType == "Word")
return new Word();
if(fileType == "Excel")
return new Excel();
}
virtual VideoFile* createVideoFiles(string fileType)
{
if(fileType == "VLC")
return new VLC();
if(fileType == "AVI")
return new AVI();
}
};
int main()
{
AbstractFactory *ptrAbFac = new ConcreteFactoryB();
Document *ptrDoc = ptrAbFac->createDocFiles("Excel");
ptrDoc->createDocument();
VideoFile *ptrVideoFile = ptrAbFac->createVideoFiles("VLC");
ptrVideoFile->createVideoFile();
}
Upvotes: 1
Views: 61
Reputation: 33931
You are close, but the Abstract Product classes (Document
and derived classes and VideoFile
and derived classes) should not have create methods. The factory does the creating and the object returned should be ready to use.
This may just be poor selection of method name, but should be corrected to prevent confusion. For the sake of your example, you can simply rename the function to DoSomething
so that you have a method you can call to demonstrate success. Example:
class Document
{
public:
virtual ~Document() = default; // must have virtual destructor
virtual void doSomething() = 0;
};
class Word: public Document
{
public :
void doSomething() override // no need for virtual.
// override helps prevent mistakes
{
cout<<"Document Word"<<endl;
}
};
The Abstract Products and AbstractFactory
need virtual destructors. Discussion of why here: When to use virtual destructors?.
In the derived classes you don't need to redeclare that the methods are virtual
. Once a method is declared virtual
in a base class, all overrides are automatically virtual
. Also, get used to using the override
keyword for methods that should override. Very useful in preventing errors should the interface change and leave you with methods that no longer override.
Don't forget to delete
all those objects the factories provided. Prefer std::unique_ptr
if it is available to you.
createDocFiles
and createVideoFiles
(both implementations) do not return in all possible paths. Eg: Nothing is returned from createDocFiles
if the provided fileType
is "Word Perfect". Compilers will usually flag this, but allow the program to compile (unless you've set warnings as errors). If a program compiles with warnings, odds are good that the program doesn't do what you want it to do. Fix:
virtual Document* createDocFiles(string fileType)
{
if(fileType == "Word")
return new Word();
if(fileType == "Excel")
return new Excel();
throw std::runtime_error("Unknown file type");
}
Upvotes: 1