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 上搜索依赖注入和框架,但您不需要遵循依赖注入原则的框架,在我看来,它们对于简单的项目来说可能有点过头了。
我有一个简单的 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 上搜索依赖注入和框架,但您不需要遵循依赖注入原则的框架,在我看来,它们对于简单的项目来说可能有点过头了。