PDA

View Full Version : Factory design pattern issue



ayanda83
26th August 2014, 17:00
hi there. I have a base class "Shape" where I derive other classes like "Circle", "Square" "Rectangle" etc. Now I have a function that takeS one parameter of type "Shape" and then within the function I have to get the name of the class that was passed to the function and I am getting the class name through QMetaObject. This is how I get the class name:
QString getClassName(Shape* shapeObj){
const QMetaObject meta = shapeObj->QMetaObject();
return meta->className();
}

Outside the function I have instantiated two instances of "Shape" in the following manner:


Shape* circleObj = new Circle();
Shape* squareObj = new Square();

After that I pass these objects to my function
void getClassName(Shape* shapeObj). This function is suppose to get the class name of a passed object. for exmple: If i pass the object "circleObj" to the function the function must return the class name "Circle" but instead the function always returns the base class name "Shape".

HOW CAN I FIX THIS?

sulliwk06
26th August 2014, 17:38
Why don't you just add a QString property to your shape class and set it to "Circle" or "Square" in the constructor for Circle and Square? It seems to me like that would be the easier way to go.

wysota
26th August 2014, 18:18
After that I pass these objects to my function
void getClassName(Shape* shapeObj). This function is suppose to get the class name of a passed object. for exmple: If i pass the object "circleObj" to the function the function must return the class name "Circle" but instead the function always returns the base class name "Shape".

HOW CAN I FIX THIS?

Do the subclasses contain the Q_OBJECT macro?

ayanda83
26th August 2014, 20:30
Do the subclasses contain the Q_OBJECT macro?
No, the sub-classes do not contain the Q_OBJECT macro because when I add it I get the attached errors. But the base class "Film" does inherit QObject and it also does contain a Q_OBJECT macro.10584

anda_skoa
26th August 2014, 20:52
The meta object is created by MOC which is only run for classes that have the Q_OBJECT macro. So if you want features from QMetaObject you'll need to add it.

The error looks like what one gets when Q_OBJECT is added to a header that is already part of the project. In such cases re-run qmake.

Cheers,
_

ayanda83
27th August 2014, 08:17
Thank And_Skoa you answered my one question but now the problem I have is that I do not have access to the member functions of the derived classes (E.G Circle and Square) instead the only functions available at my disposal is the base class functions. I suppose this has something to do with my declaration of the object; see below:

Shape* circleObj = new Circle();

There are functions exclusive to the class Circle that I want access to but instead I get access only to the base class (i.e. Shape) functions.

PLEASE ASSIST.

wysota
27th August 2014, 08:31
If you want to access functions of class X you have to do it via a pointer to class X, not its base class. You can of course do a downcast (e.g. using qobject_cast) from Shape to Circle but that usually defeats the purpose of having that common base-class in the first place. If you want to use the Factory pattern then the base class should expose the complete interface you might want to access in the instances of objects instantiated from that factory.

ayanda83
27th August 2014, 10:55
If you want to use the Factory pattern then the base class should expose the complete interface you might want to access in the instances of objects instantiated from that factory.

Thank for your reply wysota but I am a little confused by the statement you made above. I think this will defeat the purpose of "inheritance", if I have include all the properties I can possibly want for the derived classes in the base class. Maybe I am misunderstand you, but in my understanding, you are saying the member variable and functions for derived classes like "Circle", "Square", "Rectangle" ect, must all be defined in the base class "Shape". If I do this - what would be the point of deriving the classes like "Circle", "Square", etc for shape?

Let me know if I misunderstood you.

wysota
27th August 2014, 11:11
Thank for your reply wysota but I am a little confused by the statement you made above. I think this will defeat the purpose of "inheritance", if I have include all the properties I can possibly want for the derived classes in the base class. Maybe I am misunderstand you, but in my understanding, you are saying the member variable and functions for derived classes like "Circle", "Square", "Rectangle" ect, must all be defined in the base class "Shape". If I do this - what would be the point of deriving the classes like "Circle", "Square", etc for shape?


Inheritance is a much broader use-case than the Factory pattern. Factory makes use of inheritance to do its job, so its scope is much more narrow than that of inheritance itself. The goal of using a factory method is that the caller doesn't have to know the internal details of the object he wants created. If you have a factory method for "Shape objects" (ie. method returning Shape*) then it means you are not interested in what the shape actually is and you just want to handle it via the Shape interface regardless if it is a Circle, Rectangle or Square. The point of using a factory is that you don't directly tell what class of object you want created. You simply pass some parameters to the factory method and it is the factory method that makes a choice of class based on those parameters.

Consider an abstract example that you want to buy a car but you don't care what brand and model it is going to be as long as it suits your preferences. So you go to the car dealer and tell him that you want a red sedan car with electric mirrors, navigation and parking assistance. The dealer makes a choice for you and sells you ("instantiates") a particular concrete brand, model and version of a car. Then you use the car as any other car, regardless what brand and version of the car this is. You go to your friends and say "Hey, I bought a car today!" and not "Hey I bought a car of brand X, model Y in version Z today!" (in our words, you use it through the Car interface and not through "XYZCar" interface).

If that's a problem for you then maybe you don't want a factory at all. There is a number of other patterns you can employ for different needs.

anda_skoa
27th August 2014, 11:17
Inheritance/polymorphis usually defines the common things in the base class and the potentially implements them differently in the derived classes.

A method dealing with the base class pointer usually only needs to deal with the common functionality, thus not caring which derived class an object is of specifically.

If a method needs to access subclass specific methods it would either get that class as its input argument, or, as Wysota said, cast the object to that type.
This form of casting is often, but not always, avoidable.

Cheers,
_

ayanda83
27th August 2014, 11:45
Thank you wysota and Anda_skoa, your explanations are crystal clear now. It turns out that the factory pattern is not the solution to my problem according to your explanations. I have managed to solve the problem by letting go of the factory pattern and trying something else. THANK YOU!