7
\$\begingroup\$

I've some classes (Derived1, Derived2, etc.) derived from class Base. All of derived classes have a following methods (reduced sample):

void Derived1::handleTimer(const StatusType &st) {
  if (!st.isOk()) {
    m_timer->WakeUpPeriod(10); // wait for 10 seconds;
    m_timer->SetHandler(boost::bind(Derived1::handleTimer, this, _1));
    return;
  }

  try {
    ... // there is some specific for Derived's code
    m_timer->WakeUpPeriod(10 * 60); // wait for 10 minutes;
    m_timer->SetHandler(boost::bind(Derived1::handleTimer, this, _1));
  }
  catch(...) {
    m_timer->WakeUpPeriod(10); // wait for 10 second;
    m_timer->SetHandler(boost::bind(Derived1::handleTimer, this, _1));
  }
}

void Derived1::start() {
  m_timer->WakeUpPeriod(1); // wait for 1 second;
  m_timer->SetHandler(boost::bind(Derived1::handleTimer, this, _1));
}

I'd like to move these methods to Base. However, my trying looks pretty ugly. Is there more appropriate way? There is my current solution.

class Base {
public:
  typedef boost::function <void (const StatusType&)> HandlerType;
  Base(HandlerType handler) : m_hadler(handler) {}
  void start() {
    m_timer->WakeUpPeriod(1); // wait for 1 second;
    m_timer->SetHandler(m_handler);
  }
protected:
  virtual void doSomeSpecific() = 0;

  void handleTimer(const StatusType &st) {
    if (!st.isOk()) {
      m_timer->WakeUpPeriod(10); // wait for 10 seconds;
      m_timer->SetHandler(m_handler);
      return;
    }

    try {
      doSomeSpecific();
      m_timer->WakeUpPeriod(10 * 60); // wait for 10 minutes;
      m_timer->SetHandler(m_handler);
    }
    catch(...) {
      m_timer->WakeUpPeriod(10); // wait for 10 second;
      m_timer->SetHandler(m_handler);
    }
  }

private:
  HandlerType m_handler;

  ... // other data and function members
};

Now Derived classes

void Derived1::doSomeSpecific() { ... }

Derived1::Derived1() : Base(boost::bind(Derived1::handleTimer, this, _1) {}

void Derived1::handleTimer(const StatusType &st) { Base::handleTimer(st); }
\$\endgroup\$
  • 3
    \$\begingroup\$ Why would the derived classes have to override handleTimer()? Couldn't they just inherit it? \$\endgroup\$ – 200_success Dec 13 '13 at 8:50
  • \$\begingroup\$ Why do you call AsynWait on Derived1::handleTimer inside Derived1::handleTimer itself? This looks like an endless recursion to me. \$\endgroup\$ – Andris Dec 13 '13 at 9:50
  • \$\begingroup\$ @Andris - Looks like I obfuscate code trying to make sample. Thank you. See update \$\endgroup\$ – Loom Dec 13 '13 at 10:08
5
\$\begingroup\$

The use of doSomeSpecific inside of handleTimer is remarkably similar to the Template Pattern.

If there is no base implementation of doSomeSpecific you might consider making it private (still virtual so it can be overridden). Unless of course you really want further derived classes to be able to call the doSomeSpecific implementations of their parent classes.

Also, you can consider making handleTimer non-virtual if all derived classes must have the same behavior.

By making doSomeSpecific private, and handleTimer non-virtual, the only point of customization becomes doSomeSpecific, and it becomes an all or nothing point of customization. This can simplify your implementations of your derived classes, because you can trust that they only customize one specific part of your base class.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.