c++ - friend ,抽象类和工厂模式

标签 c++ inheritance factory-pattern friend

祝大家有美好的一天...

我正在公司开展一个复杂的项目,我在项目中使用了一些令人困惑的工厂设计模式。省略细节;我有一些类(我称之为“设备”),只能由“读者”创建:

class DeviceBase // this is a virtual base class
{
  public:
   //some stuff
   friend class ReaderBase; // this is OK and necessary I guess?
  private:
   DeviceBase(); // cannot create a device directly
   //some more stuff
}

class Device1: public DeviceBase // some extended device
{
  public:
   //some stuff 
  private:
   //some more stuff
}

class Device2: public DeviceBase  // some other extended device
{
  public:
   //some stuff

  private:
   //some more stuff
}

现在是“Reader”,它恰好是设备的工厂:

class ReaderBase
{
  private:
    DeviceBase[] _devices; // to keep track of devices currently "latched"
  public:
    // some other methods, getters-setters etc ...

    // this method will create the "Devices" :
    virtual bool PollforDevice ( DeviceType, timeout) = 0; 

}

现在,这是我的工厂类;但它(如您所见)是纯虚拟的。我有一个特殊的读者继承了这个:

 class InternalReader: public ReaderBase
 {
   public:
     // define other inherited methods by specifics of this reader
     bool PollforDevice( DeviceType dt, timeout ms)
     {
         switch(dt)
         {
           case Device1: { /* create new device1 and attach to this reader */ } break;
           case Device2: { /* create new device2 and attach to this reader */ } break;
         }
         // show goes on and on...
     }
 }

 class ExternalReader: public Reader
 {
   public:
     // define other inherited methods by specifics of this reader
     bool PollforDevice( DeviceType dt, timeout ms)
     {
         switch(dt)
         {
           case Device1: { /* create new device1 and attach to this reader */ } break;
           case Device2: { /* create new device2 and attach to this reader */ } break;
         }
         // show goes on and on...
     }
 }

我使用这种模式的原因是:我正在为一个可以同时连接多个这些“阅读器”的系统编写代码,并且我必须同时使用它们。

还有这些“设备”:我也可以将它们的构造函数公开,每个人都会很高兴;但我想确保它们不是由代码编写者自己创建的(以确保其他编码者)

现在问题:

  1. 我应该在每个“设备”中明确声明 ReaderBase 是好友吗?或者只是在基础上声明“DeviceBase”就足够了?
  2. 我是否应该明确放入从“ReaderBase”继承的“读者”也是这些设备的 friend 的每个“设备”,还是只放入 ReaderBase 就足够了?
  3. 我可以(并且应该)将成员方法“PollforDevice”设为友元,而不是将整个“ReaderBase”类设为友元吗?知道它是一个纯虚方法,那么继承的拷贝也会成为 friend 吗?

很抱歉这个问题很长,但我只是想弄清楚。

提前致谢...

最佳答案

为什么要担心像 DeviceBase 这样的纯抽象基类的可构造性?如果它是正确设计的契约或抽象基类,则无论如何都无法构造它。除非你必须适应某种你没有提到的框架,否则只需做与隐藏相反的事情,例如:

struct DeviceBase {
    virtual void Foo() = 0;
    virtual void Bar() = 0;
    virtual ~DeviceBase() = default;
};

顺便说一句,将构造函数或析构函数声明为 private 将非常有效地使您的类“密封”。如果由于某种原因 DeviceBase 不是抽象的(在我看来这是一个严重的设计缺陷),则使构造函数 protected 不再是 private。您需要费心的是具体 Device 类的构造函数可访问性。假设您要“发布”这些实现类(即您的库的用户可以访问它们的定义)并且您希望强调禁止直接构造,请使用“访问习惯用法”(我为此发明的名称):

namespace impl_detail {
    class DeviceAccess;
}

class ConcreteDevice1 : public DeviceBase {
    friend class impl_detail::DeviceAccess;
    // implementation of DeviceBase and all other stuff go 
    // into the "private" section
};

namespace impl_detail {
    class DeviceAccess {
        template< class TDevice >
        static DeviceBase* Create()
        {
            return new TDevice;
        }
    };
};

在您的 Reader 类中,使用 impl_detail::DeviceAccess::Create 构造 Device 实例,例如:

// Your ExternalReader::PollForDevice...
switch (dt) {
    case Device1:
        return impl_detail::DeviceAccess::Create<ConcreteDevice1>();
    case Device2: 
        // etc...
}

长话短说,最好的解决方案是根本不发布具体的实现类,其次是某种限制构建的“心理障碍”,例如上述类型...

关于c++ - friend ,抽象类和工厂模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14353551/

相关文章:

c++ - 无法转换此指针

c++ - 从基类调用派生类c++的函数

C++:继承、赋值

c# - (很多)内部方法是可以避免的吗? (接口(interface)、工厂模式)

.net - 关于依赖注入(inject)和工厂的疑惑

c++ - 通过调用 transform 方法对齐持有不同类型的两个容器

c++ - 指向预分配内存的指针作为输入参数并让函数填充它

c++ - 放置 new[] 的开销

java - 如何使用反射来构建通用子类型?

c++ - 杀死魔数(Magic Number): "const int" vs "constexpr int" (or is there no difference in the end)