C++ 注入与继承

C++ 注入与继承,c++,inheritance,C++,Inheritance,我有一个类,它从文件中读取一些数据,然后解码这些数据 我正在尝试尽可能地实现类的通用性,也就是说,我希望它能够解码任何类型的数据 解码器本身是一个通用接口 我看到两种选择: 注入-获取正确的解码器作为costructor中的参数 MyReader(解码器解码器){ _解码器=解码器} 继承-提供将返回正确解码器的虚拟方法 MyReader(); 虚拟解码器GetDecoder()=0 我的类的用户只需继承该类并只实现“GetDecoder” 注入解决方案可以帮助您减少使用的类的数量,同时让用户了

我有一个类,它从文件中读取一些数据,然后解码这些数据

我正在尝试尽可能地实现类的通用性,也就是说,我希望它能够解码任何类型的数据

解码器本身是一个通用接口

我看到两种选择:

  • 注入-获取正确的解码器作为costructor中的参数

    MyReader(解码器解码器){ _解码器=解码器}

  • 继承-提供将返回正确解码器的虚拟方法

    MyReader(); 虚拟解码器GetDecoder()=0

    我的类的用户只需继承该类并只实现“GetDecoder”

  • 注入解决方案可以帮助您减少使用的类的数量,同时让用户了解特定的编码器

    继承将需要许多类,但封装了编码器的使用

    什么是更好的方法?

    我假设您的“注入”方法是通过一个公共基类存储解码器,您考虑的替代方法更像:

    MyReader(AbstractDecoder& decoder) : _decoder(decoder) { };
    
    MyReader() { private: virtual Decoder<T>& GetDecoder() = 0; };
    
    MyReader(抽象解码器和解码器):\u解码器(解码器){};
    MyReader(){private:虚拟解码器&GetDecoder()=0;};
    
    有几个考虑因素:

    • 注入意味着客户端代码必须在创建和指定
      解码器
      、处理其生命周期内可能发生的错误方面发挥更积极的作用,而继承则隐含在派生类的选择中,错误处理可以与
      MyReader
      错误更加统一

      • 通过注入,在理解
        解码器
        是否由构造函数复制(如您所做)方面,或者调用方需要确保比读取器的生存期更长,是否可以将同一解码器传递给多个
        MyReader
        构造函数等方面,需要更多的客户端意识所有这些都有点混乱和容易出错
    • 注入意味着
      MyReader
      API可能允许在读取器的生命周期内指定另一个解码器

    • 使用继承,您将得到更多的类,客户机代码需要小心一点以避免切片,而使用注入,存储/复制时需要小心一点的是
      MyReader
      ,但至少这是集中的,而且更容易获取和保持正确


    CRTP是另一种选择,具有编译时解析和优化(死代码消除、内联等)。

    如果MyReader是一种解码器,请使用继承。否则,使用组合物(注射)。组合通常被认为是一种更好的实践,因为它增强了代码重用。它还加强了单一责任规则。继承在为访问和扩展当前类的功能提供相同的接口时很有用。因此,在您的情况下,选择1似乎更好。顺便说一下,还有其他选择,如“政策”。最好的例子是std::vector定义中的分配器模板参数。@Hsi HungShih如果解码器需要特殊初始化,我可以使用策略设计模式吗?(带参数的构造函数)?是的,您可以将策略与自定义初始化一起使用。看看如何为std::set等传递谓词。@user844541通常策略模板是无状态的,只使用它们的静态方法。如果策略模板类具有构造函数,则可以在MyReader类中构造它,然后使用它,但使用注入更合适,因为可以在MyReader类之外配置依赖关系。如果用于解码器的参数是编译时常量,则可以使用模板参数配置解码器,但我觉得这会使设计不那么清晰。