c++ - 装饰者模式 vs. 调用 super 反模式

标签 c++ design-patterns decorator anti-patterns

让我们看一个简单的装饰器示例:

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;
}

这也是Call super吗反模式?

Call super 是一种设计模式,其中特定类规定在派生子类中,要求用户覆盖方法并在特定点回调被覆盖的函数本身。

这是一个little different implementation设计上有什么不同吗?

最佳答案

这不是Call super。您调用另一个 IStuff 实例的 Info 方法,而不是覆盖版本。

调用 super 版本:

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";
  }
};

Decorator 的某些实现正在对 Decorator 基类进行 super 调用,该基类负责保存、调用和管理装饰引用:

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";
  }
};

为了避免 super 调用,您可能需要将 Decorator 与 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";
  }
};

关于c++ - 装饰者模式 vs. 调用 super 反模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12130761/

相关文章:

c++ - "contains string"的快速索引

c++ - Visual C++ 中的函数重载

linq - 使用 IQueryable<T> 的设计模式

python - 如何使用另一个类的方法装饰(monkeypatch...)Python 类?

java - JPA 和装饰者模式

c++ - 如何模拟可变参数函数中的折叠表达式?

c++ - list::remove_if 等效

python - 使用 mock 和 pytest 在 python 中模拟装饰器

java - "view"不可变对象(immutable对象)特殊情况的最佳模式

c++ - 隐藏由 PImpl 对象拥有的成员的实现