A design pattern for additional features?
I have a base class that inherits derived subclasses, it carries the basic functionality that should be the same for all derived classes:
class Basic {
public:
Run() {
int input = something->getsomething();
switch(input)
{
/* Basic functionality */
case 1:
doA();
break;
case 2:
doB();
break;
case 5:
Foo();
break;
}
}
};
Now, based on the derived class, I want to add more case statements to the switch. What are my options? I can only declare virtual functions and define them in derived classes that will use them:
class Basic {
protected:
virtual void DoSomethingElse();
public:
Run() {
int input = something->getsomething();
switch(input)
{
/* Basic functionality */
...
case 6:
DoSomethingElse();
}
}
};
class Derived : public Basic {
protected:
void DoSomethingElse() { ... }
}
But that would mean that if I change functions in any derived class, I will have to change the base class to reflect those changes.
Is there a design pattern specifically for this kind of problem? I've bought several books on design patterns, but I'm learning them on an "as needed" basis, so I have no idea if there is a pattern I'm looking for.
a source to share
You can find useful information about the chain of responsibility and rethink your decision that way.
Alternatively, you can declare "doRun" as a protected method and call it in the default base case.
default:
doRun(input);
And define doRun in derived classes.
This is the so called template template template
a source to share
The usual way to deal with this is to use a factory. In the diagram:
- create a hierarchy of related classes that provide functionality.
- create a factory class that takes input and instantiates the appropriate class based on the input
Now for extra bonus points:
- create a schema that regresses classes with a factory - you will need to specify the input and type of the class to handle it.
Now, when the need for a new input arises, you just get a new class and register it with a factory. The need for a switch statement disappears.
But that would mean that when changing functions in any derived class, I would have to change my base class to reflect those changes.
Why is this so?
I will remember your comment - then if you take this approach, you will have problems. Others have posted answers that suggest other solutions - I would check them to see if they help you.
a source to share
If your selector values are small integers, I would replace the case statement with a lookup table. (The actions in this case must be coded as a function, so you can put function pointers in a table). The inherited classes can then simply add records to the table. (I think the table should be an instance property, it cannot be static).
Colin
a source to share
A simple solution:
class Basic {
public:
void Run() {
const int input = ...
if (!(BaseProcess(input) || Process(input))) ...
}
vitual bool Process(int input) { return false; }
bool BaseProcess(int input) {
switch(input) {
...
default: return false;
}
return true;
}
...
... and then implement additional cases in the Process () subclass. If you need to support more than two levels (for example a sub-subclass, adding even more cases), you need a dynamic mailing table.
a source to share