How to design meaningful objects and their relationships in simple physic simulations
我正在尝试使用OOP范式设计一些简单的实时模拟。我面临的问题是,由于我缺乏这种方法的经验,我不知道如何自然地定义"正确"的对象及其关系。因此,我的问题更接近于软件架构,而不是更技术的"如何实现这个或那个"。注意,我做这个练习是为了了解这个编程范式。
模拟试图解决在空的二维空间中粒子之间的相互作用(碰撞、吸引等)。我想到的第一个目标是Particle。我已经用位置、速度、质量等实现了这个类。我已经创建了方法来启动它们,更新它们的位置(根据一些物理规则),甚至在画布中绘制它们。现在,我的问题出现在设置物理常量或绘图参数(画布大小、窗口编号、每秒帧数等)时。现在我使用的是全局变量,比如重力或画布大小。这是在非OOP方法中所做的,它能操作OS。但我一直在苦苦思索纯OOP如何处理粒子间的共享参数。我可以预见各种各样的选择。
我可以用图形参数创建类Canvas,用重力等常量创建类Universe。那么,类Particle将是一个扩展类。但我应该从哪继承呢?不过,类会被扩展,但对象本身不会……
另一种选择是创建Universe和Particle作为独立类。然后,我将通过创建一个独特的宇宙对象来联系他们。每个粒子都包含一个指向这样一个宇宙物体的指针,因此它们可以访问物理参数。我不确定这个指针方法是否甚至是OOP…
虽然我知道有很多方法可以做到这一点,但我想知道是否有一种方法至少从学术的角度来看更为直观和"标准"。我想它不包括在我提出的解决方案中,所以关于如何在这种简单的模拟中设计结构的任何提示都是非常受欢迎的。
- 小心:OOP和性能可能难以结合。programmers.stackexchange.com/questions/125753/…
这是一个更实际的考虑,主要是从我自己的经验,并严格尝试在基本设计考虑的水平。我会对反馈很感兴趣。
首先,从设计的角度来看,你的"画布"和"宇宙"似乎是不同的:我可以想象画布参数可能需要改变,而物理常数可能不会。
假设画布实体可能会改变,对我来说,这将是一个单独的类。我不认为你会希望你的粒子从中继承;在我的理解中,这些是逻辑上完全分离的实体。为了方便在画布上放置粒子,我将在不同的层次上处理它,而不是通过继承。
粒子本身可以用类的层次结构来实现,但这取决于您的项目以及是否有不同类型(或行为)的粒子。
至于固定的参数,我在C++项目中使用了单独的头文件,其中有显式的名称空间。我不认为这是Fortran中不可行的设计的原因,因为它使用了一个单独的带有常量的模块。从这个意义上说,它们是全球性的,但可以在使用中加以控制,这就是它们的本质。这种方法也有一定的灵活性,以防您的常量集比仅仅是几个数字变得更复杂。此外,如果证明需要,可以稍后将此提升到类。
还有一些问题,这些与其他类的关系到底如何,以及如何编写这些类的许多细节。这将把问题带到其他地方,我对Fortran的全部OO功能(除了编写类)并不熟悉。
所以我会说:"画布"是一个类,"宇宙"是一个模块,两者都与粒子分离。
- 谢谢你的回答。但我仍然担心,我如何将"宇宙"和"画布"联系起来?我将给出一个简单的例子:我遇到的一个真正的问题是画布有一个标识窗口的ID(这个ID用于低级绘图子例程)。我在"粒子"中有一个方法,它在给定的坐标中画一个圆,但它需要这样的ID。我如何让一个粒子知道它在给定的"画布"中"存在"这个事实呢?在我当前的实现中,这样的ID是类"粒子"的一部分,我认为这是一个跛脚的解决方案。
- @对于Turenio,我不会在设计级别考虑这些因素。为什么粒子会被画布缠住?只是在作图,是吗?它的行为不受画布的影响,对吗?如果需要了解画布属性——那么,Canvas是一个具有您设计的接口(访问方法)的类,因此每个人都可以获取他们可能需要的信息。你可以更紧密地整合它们,但是让另一个继承链的一部分给我带来不合适。
- @在回顾以前的帖子时,我遇到了这个有趣的问题。你最后做了什么?我也建议把这个贴出来,作为将来访问这个页面的回答。(如果是短的和你自己的,如果是最好的,也可以。)