OOP and Design Practices: Accessing functionality of member objects?
我一直在使用C++进行一个小项目(虽然这个问题可能被认为是语言不可知的),我试图写我的程序,使它尽可能高效和封装。我是一个自学成才、经验不足的程序员,但在使用界面和OOP实践方面,我正在努力让自己养成良好的习惯。当涉及到访问作为另一个类的子系统的对象的方法时,我主要对典型的"最佳"实践感兴趣。
首先,让我解释一下我的意思:
我的问题是,ClassGame对象可以间接地利用ClassRenderer的功能,同时仍然保持快速和抽象层的后面。从我在课程和其他人的代码示例中所看到的,似乎有两种基本的方法可以做到这一点:
我通过一系列关于OOP设计的在线讲座学到的第一个方法是让一个类在内部将任务委托给它的私有成员对象。[在本例中,ClassGame将调用属于ClassEngine的方法,ClassEngine将通过调用其方法之一将该请求"秘密"传递给它的ClassRenderer子系统。]类似于函数调用的"菊花链"。这对我来说是有意义的,但似乎比其他选择要慢。
我在其他人的代码中看到的另一种方法是访问一个特定子系统的位置的引用或指针的访问器方法。[因此,ClassGame将调用ClassEngine中的一个简单方法,该方法将返回对构成其ClassRenderer子系统的对象的引用/指针]。这条路线对我来说似乎很方便,但它似乎也消除了让一个私有成员充当更大类的子组件的问题。当然,这也意味着只需编写简单地传递特定任务的"无意识"函数要少得多,因为您可以为每个独立的子系统简单地编写一个getter函数。
考虑到OO设计的各个重要方面(抽象、封装、模块化、可用性、可扩展性等),同时考虑到速度和性能,最好使用第一种或第二种方法将任务委托给子组件吗?
书中的设计模式解释了一个非常相似的问题,在其章节中关于桥梁模式。很明显,这一章在网上是免费的。
我建议你读一下:)
我认为你的1型方法最像OOP桥型。
类型2,将句柄返回到内部数据通常是应该避免的。
有很多方法来做你想做的事情,这真的取决于上下文(例如,项目有多大,你希望在其他项目中重用它)。
你有三个类:游戏、引擎和渲染器。这两种解决方案都使游戏提交到引擎的接口。第二个解决方案也使游戏提交到渲染器的界面。显然,您使用的接口越多,接口更改时所需的更改就越多。
第三个选项怎么样:游戏知道它在渲染方面需要什么,所以您可以创建一个描述这些需求的抽象类。这将是游戏所承诺的唯一接口。让我们称这个接口为AbstractGameDrenderer。
要将其与系统的其他部分联系起来,还有很多方法。一个选择是:1。使用现有的呈现器类实现这个抽象接口。所以我们有一个类gamerenderer,它使用渲染器并实现abstractgamerenderer接口。2。引擎创建游戏对象和游戏渲染器对象。三。引擎将gamerenderer对象传递给game对象(使用指向abstractgamerenderer的指针)。
结果:游戏可以使用渲染器来实现它想要的。它不知道它来自何处,如何呈现,谁拥有它——什么都不知道。游戏渲染器是一个特定的实现,但是其他实现(使用其他渲染器)可以稍后编写。发动机"无所不知"(但这可能是可以接受的)。
稍后,您需要将您的游戏逻辑作为一个迷你游戏在另一个游戏中使用。您所需要做的就是创建适当的游戏渲染器(实现AbstractGame渲染器)并将其传递给游戏对象。游戏对象并不关心它是一个不同的游戏,一个不同的引擎和一个不同的渲染器-它甚至不知道。
重点是设计问题有很多解决方案。这个建议可能不合适或不可接受,或者可能正是你需要的。我尝试遵循的原则是:1。尽量不要提交到你无法控制的接口上(如果它们改变了,你就必须改变)2。现在试着预防以后会有的疼痛。
在我的示例中,假设在渲染器更改时更改游戏渲染器比更改大型组件(如游戏)更容易。但最好坚持原则(尽量减少痛苦),而不是盲目地遵循模式。