Frage

Let's have a simple Decorator example:

struct IStuff {
  virtual void Info()=0;
  virtual ~IStuff() { }
};

class Ugly : public IStuff {
public:
  void Info() { cout  << "Ugly"; }
};

class Shiny : public IStuff {
  IStuff* stuff;
public:
  Shiny(IStuff* stuff) {
    this->stuff = stuff;
  }
  ~Shiny() {
    delete stuff;
  }
  void Info() {
    stuff->Info(); // <------------------------------- call super?
    cout << "->Shiny";
  }
};

int main() {
  IStuff* s = new Ugly();
  s = new Shiny(s); // decorate
  s = new Shiny(s); // decorate more
  s->Info(); // Ugly->Shiny->Shiny
  delete s;
  return 0;
}

Is this also the Call super anti-pattern?

Call super is a design pattern in which a particular class stipulates that in a derived subclass, the user is required to override a method and call back the overridden function itself at a particular point.

Here is a little different implementation Is there any difference in design?

War es hilfreich?

Lösung

This is not Call super. You call the Info method of another IStuff instance, not the overriden version.

Call super version:

struct IStuff {
  // If you override this, you MUST call the base class version <-- call super
  virtual void Info()
  {
    // a default implementation.

    std::cout << "Super call ";  
  }
  virtual ~IStuff() { }
};

class Shiny : public IStuff {
public:
  void Info() {
    IStuff::Info();  // don't forget to call base implementation.
    std::cout << "->Shiny";
  }
};

Some implementations of Decorator are making a super call to a Decorator base class, that is responsible to hold, call and manage the decorated reference:

struct IStuff 
{
  virtual void Info() = 0;
  virtual ~IStuff() { }
};

class Stuff : public IStuff
{
public:
    void Info() { std::cout << "Basic stuff"; }
};

class StuffDecorator : public IStuff
{
    IStuff* decorated_;
public:
    StuffDecorator(IStuff* decoratedStuff) :
        decorated_(decoratedStuff) {}
    ~StuffDecorator() { delete decorated_; }

    void Info()
    {
        decorated_->Info();
    }
};

class Shiny : public StuffDecorator 
{
public:
  Shiny(IStuff* stuff) : StuffDecorator(stuff) { }

  void Info() 
  {
    StuffDecorator::Info();
    std::cout << "->Shiny";
  }
};

To avoid the super call you might want to combine Decorator with Template Method:

class StuffDecorator : public IStuff
{
    IStuff* decorated_;
public:
    StuffDecorator(IStuff* decoratedStuff) :
        decorated_(decoratedStuff) {}
    ~StuffDecorator() { delete decorated_; }

    void Info()
    {
        decorated_->Info();
        DoInfo();
    }
private:
    // Template method
    virtual void DoInfo() = 0;
};


class Shiny : public StuffDecorator 
{
public:
  Shiny(IStuff* stuff) : StuffDecorator(stuff) { }
private:
  void DoInfo() 
  {
    std::cout << "->Shiny";
  }
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top