Question

I have a basic class that derived subclasses inherit from, it carries the basic functions that should be the same across 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 here? I can declare virtual functions and only define them in the derived classes that are going to 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 this would mean when changing functions in any derived class, I would have to edit my base class to reflect those changes.

Is there a design pattern specifically for this kind of issue? I purchased a number of books on Design Patterns but I'm studying them on "by-need" basis, so I have no idea if there is such a pattern that I am looking for.

Was it helpful?

Solution

You may find useful to read about Chain of responsibility pattern and rethink your solution in that way.

Also you can declare 'doRun' as protected method and call it in the base default case.

default:
   doRun(input);

And define doRun in derived classes.

This is so called Template Method pattern

OTHER TIPS

I think the pattern you need is Chain Of Responsibility or maybe Strategy combined with a dynamic call table...

The normal way of dealing with this is to use a factory. In outline:

  • create a hierarchy of related classes that provide the functionality.
  • create a factory class that takes the input and creates an instance of the right kindf of class depending on the input

Now for added bonus points:

  • create a scheme that reghisters classes withn the factory - you will need to specify the input and the type of the class to deal with it

Now when a need for a new input comes along, you just derive a new class and register it with the factory. The need for the switch statement disappears.

If your selector values are just small integers, I would replace the case statement by a lookup table. (The actions in the case will each need to be coded as a function, so you can put function pointers in the table). Then inherited classes can just add entries to the table. (I guess the table would have to be an instance property, it can't be static).

Colin

But this would mean when changing functions in any derived class, I would have to edit my base class to reflect those changes.

Why would this be true?

I light of your comment - then if you choose this approach you'll have these issues. Others have posted answers that suggest other solutions - I'd check these out to see if they help you.

А 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 subclass' Process(). If you need to support more than 2 levels (i.e. sub-subclass adding even more cases), then you'll need a dynamic dispatch table.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top