C ++中包装类的设计

时间:2017-04-24 09:48:34

标签: c++ design-patterns wrapper

我必须使用一个非常笨拙的界面的旧类。由于我无法改变它并依赖它,我想构建一个包装器,提供一个干净的界面。假设我有一个 ClumsyClass 类。基本上,我有三种方法:

1。参考会员

    Class Wrapper {
      public:
        Wrapper (ClumsyClass& clumsyClass)
          : m_clumsyClass(clumsyClass)
        { }

        int getSmth() {
          return m_clumsyClass.getSmth();
        }

        private:
          ClumsyClass& m_clumsyClass;
}

2。指针成员

    Class Wrapper {
      public:
        Wrapper (ClumsyClass* clumsyClass)
          : m_clumsyClass(clumsyClass)
        { }

        int getSmth() {
          return m_clumsyClass->getSmth();
        }

        private:
          ClumsyClass* m_clumsyClass;
}

第3。继承

    Class Wrapper : public ClumsyClass {
    ...
}

哪种方法是实现包装器的“最干净”的方法?我更喜欢第三个,但是当我已经有一个ClumsyClass对象然后创建一个Wrapper对象(复制构造函数)时,将需要更多的内存(因为在我的情况下,原始类的实例是必需的。)

2 个答案:

答案 0 :(得分:1)

我会避免使用3,因为它无法封装ClumsyClassWrapper的用户可以有意或无意地直接访问"笨拙的" ClumsyClass的界面,这是你要避免的。更喜欢继承的组合。

1.和2.之间的差异很小。使用引用成员使包装器不太灵活。该类不可分配,您不能重新引用该引用并将其替换为ClumsyClass的其他实例,并且该成员不能为空。根据您的要求,这些可能是好的或坏的。

但正如评论中所述,默认选择应该是ClumsyClass作为Wrapper的按值成员:

class Wrapper {
  public:
    // possible constructors
    //Wrapper(const ClumsyClass& cc) : m_clumsyClass(cc) {} // copy 
    //Wrapper(ClumsyClass&& cc) : m_clumsyClass(std::move(cc)) {}  // move 
    int getSmth() { return m_clumsyClass.getSmth(); }

  private:
    ClumsyClass m_clumsyClass;
};

在您的特定用例中,为什么这可能不可能或不可取,有很多原因,然后您可以回退到选项1或2.该决定主要取决于所有权。应Wrapper"拥有" ClumsyClassClumsyClass的实例的有效期是否超出Wrapper

使用直接成员的一个潜在缺点是你不能再隐藏前向声明后面ClumsyClass的实现,这样你就失去了ClumsyClass的一些封装。值得注意的是,解决这个问题的一种方法是提取出一个抽象的基类" interface" Wrapper继承自。{1}}。类似的东西:

class IWrapper {
  public:
    virtual ~IWrapper() {}
    virtual int getSmth() = 0;
};

可能会提供额外的好处,例如可测试性。

答案 1 :(得分:0)

从你提到的限制看来,这可能是一种可行的方法:

使用您想要的方法创建一个界面

struct IMyMethods 
{
  virtual int getOther() = 0;
  ...
  virtual ~IMyMethods() {};
};

现在创建一个新类,派生自您的类和要在添加接口实现的类上使用的接口

class MyAgileClass : public ClumsyClass, IMyMethods
{
public:
   MyAgileClass(/*same args as for ClumsyClass*/)
   {}
   ~MyAgileClass() 
   {}

   virtual int getOther() 
   {
     return getSmth(); // clumsy class function
   }
   ...
};

您现在可以直接访问ClumsyClass,也可以通过简化的界面

访问ClumsyClass