views:

90

answers:

3

I have a class that is used as a member in many places in my project. Now, instead of this class I want to have a polymorphism, and the actual object will be created by some kind of factory.

I have to choose between:

  1. Having to change all the places where I use the class - to call the factory and use a pointer instead of object directly.
  2. Changing the class to be just a wrapper, that will call functions of a new polymorphic class I will create.

Which strategy should I better choose?

+4  A: 

Change all the places where I use the class to call the factory and use a pointer instead of object directly.

That's best. It seems painful at first, but it's clean and more extensible than implementing a wrapper because you didn't feel like doing a search for new MyClass(.

Once you list all the place with the new, you'll see that it isn't really all that bad a job.

S.Lott
You can even let the compiler help you if you make the class-that's-used-everywhere abstract (by defining one virtual function with `=0` at the end), and then the compiler will helpfully point out all of the places where you have to change it!
dash-tom-bang
+2  A: 

Chances are that even if you go with #2 and implement a base class wrapper, you will have to modify the client code anyway (different methods of construction through a factory, e.g., for a polymorphic base wrapper).

I'd go with #1 but not a regular pointer, but something like boost::shared_ptr or boost::scoped_ptr (depending on what you need).

The second option might allow you to take some liberties with the base wrapper interface, but I'd recommend against that: favor the commonly-accepted approaches when possible. If the base class wrapper provides additional facilities that boost::shared_ptr doesn't provide, e.g., it will be a foreign entity which introduces new concepts in the system and probably with little or no benefits to show for it.

In the best case scenario, your base class wrapper duplicates the interface of something common and familiar to most developers like boost::shared_ptr, in which case it's reinventing the wheel and you might as well have used boost::shared_ptr. In the worst case scenario, your wrapper class introduces an interface that's completely different and therefore introduces foreign code to the system that others will not immediately recognize.

No matter how good you are, other developers will have a much easier time trusting and working with a peer-reviewed, well-documented, thoroughly-tested library like boost than a handrolled solution by one engineer. If only for that reason, try to use the existing library solutions as much as possible and prefer those to, say, a custom base class wrapper.

+1  A: 

Your idea of using a wrapper even has a name. It's the letter/envelope idiom, as described by Coplien (before they started to call these idioms "patterns").
Google finds you more explanations for it.

Contrary to the others I don't see anything wrong with using it. For the class' users, it's much easier to deal with something that behaves as simple as a value type. No hassle of having to use a factory or a factory method for creating objects, since the class' constructors are the factories - which is what constructors were invented for in the first place.
What could be wrong with that?

sbi