注入vs.继承

Injection vs. Inheritance

本文关键字:继承 vs 注入      更新时间:2023-10-16

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

我试图做类尽可能泛型,即我希望它能够解码任何类型的数据。

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

我看到两个选项:

  1. 注入-在构造函数

    中获得正确的解码器作为参数

    MyReader (Decoder解码器){

  2. 继承-提供一个虚拟方法,将返回正确的解码器

    MyReader ();虚拟Decoder GetDecoder () = 0;

    我的类的用户只需要继承这个类并只实现"GetDecoder"。

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

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

什么被认为是更好的方法?

我猜你的"注射";方法将通过公共基类存储解码器,并且您正在考虑的替代方案更像是:

MyReader(AbstractDecoder& decoder) : _decoder(decoder) { };
MyReader() { private: virtual Decoder<T>& GetDecoder() = 0; };

有几个注意事项:

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

    • 注入,有一点更多的客户端意识在理解Decoder是否被构造函数复制(如你所做的),或者调用者需要确保生命周期大于读者,是否相同的解码器可以传递给多个MyReader构造函数等方面是必要的。-所有的有点混乱和容易出错
  • 注入意味着MyReader API可能允许在读取器的生命周期内指定另一个解码器

  • 与继承,你最终有更多的类和客户端代码需要小心一点,以避免切片,而与注入它的MyReader本身,需要在存储/复制时有点小心,但至少这是集中的,因此更容易获得和保持正确的

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