我最近创建了一个“通信”对象/抽象类,我可以在其上使用这些函数: “发送”,“接收”,“调试发送”等。
现在,我想在基本上所有其他类中使用此对象,以便我可以使用它来发送调试消息。
目前我必须这样做:
#include "../communication/ICommunication.hpp"
extern Communication* comm;
在我想要使用此对象的任何其他文件/类中。 虽然这看起来效果很好,但我想知道是否有更简洁的方法来做到这一点。
我相信有一个软件模式,虽然我不记得名称,也没有实现。我相信,模式的名称是一个人的姓氏。
我想知道这个模式的名称(或任何有利于此目的的模式),所以我可以自己尝试实现。 如果可能的话,还有一些关于为什么这种模式比“包含和外部”代码更好的论据。
答案 0 :(得分:2)
我想知道这个模式的名称(或任何有利于此目的的模式),所以我可以自己尝试实现。如果可能的话,还有一些关于为什么这种模式比“包含和外部”代码更好的论据。
目前使用的最佳实践是界面抽象和依赖注入:
首先抽象您要在comm对象上使用的操作:
struct Communicator
{
virtual void send(const std::string&) = 0;
virtual std::string receive() = 0;
// etc
};
// injectable Communicator implementation that does nothing; this is useful as
// a default argument for code that uses communicators: it will show the dependency
// explicitly, but setting it as a default argument ensures that client code
// doesn't _have to_ use a communicator, if you don't have one available
struct NoOpCommunicator: Communicator
{
void send(const std::string&) override {}
std::string receive() override { return {}; }
} dummy_communicator; // <--- notice this global
客户代码:
class YourClientCode // (uses a Communicator)
{
public:
YourClientCode(Communicator& c = dummy_communicator) // communicator instance,
// dependency injected here
: com(c)
{
}
private:
void f() { com.send("f()"); /* ... */ }
Communicator& com;
};
auto client1 = YourClientCode{};
auto client2 = YourClientCode{ GetActualCommunicatorReference() };
这比include + extern更好,因为它不会对通信器的依赖性进行硬编码,并且不强制为了使用客户端代码而你必须启动并运行通信器。这大大提高了代码的可测试性和可重用性。
答案 1 :(得分:1)
这种模式叫做singleton(通常称为反模式)。它应该如下所示:
struct MySingleton {
static MySingleton& getInstance() {
static MySingleton singleton;
return singleton;
}
};
更好的方法是将Communication
实例作为构造函数的参数传递给每个类。您也可以将其包装到shared_ptr
中,这样一旦所有类都不再引用它,将自动调用Communication对象的析构函数。
如果可能的话,还有一些争论为什么这种模式比&#34; include和extern&#34;更好?代码。
我认为您可能遇到的一个问题是如何管理您的通信对象生存期。它应该在第一次使用之前创建,我想它应该在任何其他类或函数可能想要使用它之后销毁。
我不确定singleton是否适用于Communication对象,我假设您使用它与服务器建立连接,并在一段时间后断开连接。这可以用西格尔顿来完成,但根据我的经验,单身人士更多地用于生命周期更长的物体,比如整个应用期间。