I'm currently refactoring a class that looks (after some refactoring and very much simplified) somewhat like this:
class Foo
{
public:
Foo(bool someFlag) : m_flag(someFlag) { };
void doThings();
void doOtherThings()
{
doPrivateThings();
if (m_flag)
doFlagThings();
else
doNoFlagThings();
}
private:
void doPrivateThings();
void doFlagThings();
void doNoFlagThings();
bool m_flag;
}
Notes:
* m_flag
being there is the result of the refactoring (which is by far not done) – initially each function individually branched (if (check_something())
) on something that for which the result was already determined/fixed during construction of the object.
* The functions doFlagThings()
and doNoFlagThings()
are rather small (~3-5 lines of code) and there are at most 3-4 functions that deviate depending of m_flag
.
So, the next step is to get rid of the someFlag
– the only question is how.
One way would be to use an abstract parent and inheritance:
class FooBase
{
public:
FooBase();
void doThings();
void doOtherThings()
{
doPrivateThings();
doSpecializedThings();
}
private:
void doPrivateThings();
virtual void doSpecializedThings() = 0;
}
class FlagFoo : public FooBase
{
public:
FlagFoo();
private:
void doSpecializedThings() override { ... };
}
class NoFlagFoo : public FooBase
{
public:
NoFlagFoo();
private:
void doSpecializedThings() override { ... };
}
The other way would be to use the Strategy pattern and composition, i.e.
class Foo
{
public:
Foo(IDoThingsStrategystrategy strategy) : m_Strategy(strategy) { };
void doThings();
void doOtherThings()
{
doPrivateThings();
m_Strategy.doSpecializedThings();
}
private:
void doPrivateThings();
IDoThingsStrategy m_Strategy;
}
class IDoThingsStrategy
{
public:
IDoThingsStrategy();
virtual void doSpecializedThings() = 0;
}
class DoThingsFlagStrategy : public IDoThingsStrategy
{
public:
DoThingsFlagStrategy();
void doSpecializedThings() override;
}
class DoThingsNoFlagStrategy : public IDoThingsStrategy
{
public:
DoThingsNoFlagStrategy();
void doSpecializedThings() override;
}
But that seems very much like overkill, and presents the problem that the creator of Foo
now needs to be aware of the different Strategies in order to create them and feed them to Foo
.
So the question is: Should I go with the Inheritance (even though one should prefer composition over inheritance) or the Strategy pattern or is there a better way I'm just not seeing right now?
Best Answer
In short
Your code is the typical example for applying the template method design pattern:
So go for your first refactoring option, because it's exactly what you intend to do.
More explanations**
Your current code of
doFlagThings()
anddoNoFlagThings()
may perfectly well use protected or private members, because currently they are both member functions.With the template method pattern, you wouldn't bother about this (except perhaps some private members that would have to become protected when refactored in the
FooBase
class.THe strategy template intends to encapsulate a family of alogrithm to make them usable interchangeably. In your case:
doFlagThings()
anddoNoFlagThings()
would be very independent of the rest of the class, it would certainly be a valid alternative;Foo
, and in addition pass the calling object as parameter so that the strategy can invoke the right functions and access to the right member variables. So you'd have a false strategy, where you'd have a very strong coupling between all the classes. Not exactly the intent of the pattern...But why do you hesitate ? You've identified by yourself that the strategy would be overkill in your situation. Is it perhap's because you have the mantra "composition over inheritance" in your head ? Then be reassured: it's just a rule of thumb and not a golden rule. There are cases where inheritance really is the best solution (otherwhise there would be no inheritance in OOP ;-) )