在我的项目中,我将多个子系统组织为类。
我需要这些类进行通信(因此能够通过指针访问另一个),我希望尽可能以最佳方式实现它。
我基本上在这里看到三种可能的解决方案:
如果子系统X需要访问子系统Y,则将一个成员变量添加到指向Y实例的类X.创建X时,向其传递指向Y的指针并使其具有成员变量{{1} } set。
为每个子系统声明一个全局变量m_pSystemY
。它将在程序启动时填充指向新创建的子系统实例的指针。稍后,您可以从任何地方轻松访问它。
创建复杂的子系统管理器类。所有子系统都存储在一个数组中。您需要调用函数才能访问特定的子系统。
我的问题:
我应该将哪些解决方案用于我的游戏引擎项目?
您是否有任何这些方法的个人经验?
答案 0 :(得分:2)
通过指向其他类的指针暴露整个类将在整个系统中产生紧密耦合,从而打破了“demeter法则”。您可以通过已知的设计模式使其更好,例如:中介模式。只是一个想法...
答案 1 :(得分:2)
多么有趣,我看到每个方向都有一个答案!
无论如何,我建议您按照选项#1(将成员变量添加到指向Y实例的X类)进行一次小修正:使用界面。
因此,每个模块都有一个接口。该界面将具有外部人员可能需要完成其工作的方法。其他一切都隐藏起来了。
创建模块A时,如果需要使用模块B的功能,您将执行类似setModuleBHandler(moduleB)
的操作。
通过这种方式,您可以更改执行所需操作的模块,而无需调用者注意到它(因为接口仍然受到尊重)。
这将允许您遵循其他良好做法,例如TDD。
示例:强>
假设模块Broker需要记录(并且您有一个专用于记录的模块)。而不是声明public void setLogger(Logger logger)
,而不是声明如下:public void setLogger(LoggerInterface logger)
。
这几乎是一样的。以前的工作仍然有效。不同之处在于,现在您可以使用一些完全不同的Logger实现,而不必担心可能使用它们的无数模块中的影响。
例如,您可以使用实现接口的类TextLogger和实现相同接口的另一个DBLogger。您可以在不预期任何问题的情况下进行交换。
注意:使用抽象类会得到几乎相同的结果。
我知道这个小例子没有正确显示这个选择的全部优点,很多人都能找到它的缺点,但我坚信这是大多数情况下的最佳选择(当然每个案例是一个案例)。
答案 2 :(得分:0)
我根本不会使用全局变量。我会通过初始化函数将指针传递给其他系统。无论是谁实例化这些系统并初始化它们都可以决定如何存储它们,可以是它们自己的全局变量,静态类成员,单例包装器,或者(最合适的)某个统一类的成员(IE:类CGame)。无论哪种方式,在初始化时传递它们是最模块化,可读和可维护的,而不会以任何方式牺牲易用性。
答案 3 :(得分:0)
我会选择子系统管理器类。我将使用模板实现这一点,并确保子系统实现相同的接口(即c#lingo不确定c ++等价物是什么)所以他们可以互相交谈。
答案 4 :(得分:-2)
如果您的课程总是只有一个实例,那么您可以将它们视为单身:
class singleton
{
// Private constructor
singleton() {}
// Static instance defaul to null in cpp
static singleton *instance;
public:
// Access function (put in cpp)
static singleton* getInstance()
{
if(!instance) instance = new singleton();
return instance;
}
};