Wrapper class 设计和依赖注入

Wrapper class design and dependency injection

我有一个简单的 FTP class 负责通过 cURL 库进行下载和上传:

class FTPClient
{
public:
    explicit FTPClient(const std::string& strIPAddress);
    virtual ~FTPClient();

    bool DownloadFile(const std::string& strRemoteFile, const std::string& strLocalFile);
    bool UploadFile(const std::string& strLocalFile, const std::string& strRemoteFile);

private:
    static size_t WriteToFileCallBack(void *ptr, size_t size, size_t nmemb, FILE *stream);
    static size_t ReadFromFileCallback(void* ptr, size_t size, size_t nmemb, FILE *stream);

    std::string m_strUser;
    std::string m_strPass;
    std::string m_strIPAddress;
    std::string m_strPort;

    mutable CURL* m_objCurlSession;
};

我已经询问了一些关于如何更好地实施和构建它的建议,因为它是项目的基础和核心,并且将在许多部分中使用。 有人告诉我使用 cURLWrapper class 来包装所有 cURL 调用 (curl_easy_setopt(..)),但后来有人告诉我为 [=23= 创建一个接口] class,一个只调用 FTP 方法的 cURLWrapper,然后是一个具体的 class.. 但它对我来说仍然太抽象了,不明白实现它的最佳方法以及哪个要遵循的路径..

你会如何处理这个小结构?

为您的 FTP class:

定义一个简单的界面
class IFTPClient
{
public:
    virtual ~IFTPClient();

    virtual bool DownloadFile(const std::string& strRemoteFile, const std::string& strLocalFile) = 0;
    virtual bool UploadFile(const std::string& strLocalFile, const std::string& strRemoteFile) = 0;
};

我假设您的静态回调方法正在回调某些 class 实例而不是单例?那好吧。从接口导出你的class:

class FTPClient:IFTPClient
{
    ...

我注意到您已将 IP 地址传递到构造函数中,并在别处定义了其他参数(用户名、密码、端口等)。这似乎还不太一致。您需要对其进行重构,以便可以通过接口方法设置这些参数或将它们添加到 upload/download 方法中。

在其他地方需要它之前构建您的 FTPClient 对象,然后仅将接口传递 ("inject") 到想要使用 FTPClient 的对象中。对于不使用实际 FTPClient 的单元测试,构造一个从同一接口派生的模拟对象并将其注入其他对象。

其他对象只是利用接口中公开的功能,不需要知道或担心其内部实现;如果您决定使用 curl 或其他东西,则完全取决于 FTPClient.

简而言之;您可能想在 Internet 上搜索依赖注入和框架,但您不需要遵循依赖注入原则的框架,在我看来,它们对于简单的项目来说可能有点过头了。