共计 2344 个字符,预计需要花费 6 分钟才能阅读完成。
由“树状线条求最长门路问题”浅谈“面向对象”编程的思维形式(AutoCAD.net)
网友给了这样一个需要:求此图最长门路:
图上为首尾相连个一组线,要求性能是点其中的某一条线,求通过此线的最长一条门路。
后果如图:
我用各种办法试了一下,感觉别不现实。起初我想了想,发现这就是一棵树啊!依据面向对象的编程思维。我第一步应该是定义一个树对象的类。
期间我发现用树的概念去形容一些问题不太不便,如果退出“家族树”的概念,就容易一些。家族树和树是一个性质的。所以我退出了家族树的概念在外面。
定义类 CurvesTree
首先咱们能够想到,他应该有个“自己”的属性:是一条 Curve。
而后在他上面和他相连的线都能够称为他的孩子。而他的每一个孩子也是一个 CurvesTree。所以“孩子们”属性:List< CurvesTree > 孩子们;
而后在他的下面和他相连的线能够称为他的父亲。而他的父亲也是一个 CurvesTree。父亲属性:CurvesTree 父亲;
咱们能够看到,这样的一个类,他是一个递归类。递归类的属性蕴含他这个类自身。递归类如何结构呢?前面揭晓。
那么作为一个家族树里的一个成员,咱们应该晓得那些事件呢?
咱们应该晓得父亲的父亲,以及父亲的父亲的父亲……直到第一代先人。所以咱们须要一个属性,叫做所有先辈。List< CurvesTree > 所有先辈;
显然,咱们还须要晓得咱们的第一代先人:CurvesTree 先人。
咱们还应该晓得所有孩子的孩子,那么就是所有后辈:List< CurvesTree > 所有后辈。
那么,第一代的先人是没有父亲的,最末的后辈是没有孩子的。所以咱们定义两个逻辑属性:bool 有孩子。bool 有父亲。
咱们回到线的概念上来,一条线下面连着父亲,上面连着孩子们,所以咱们要定义两个属性,一个是头,一个是脚。头连着父亲,脚连着孩子们。Point3d 头,Point3d 脚。
须要计算长度,所以咱们须要定义一个长度的属性。这个长度不仅仅是自己这条线的长度,还应该蕴含直到先人的长度,也就是累计长度。所以定义一个累计长度的属性,double 累计长度。
累计长度如果在没有父亲的时候,就是自己 Curve 的长度。如果有父亲,则是自己 Curve 的长度加上父亲的累计长度。
于是咱们就能够晓得,先找到所有没有孩子的后辈,而后找到其中累计长度最长的,那么他的所有先辈加上他本人,也就是从第一代开始最长的一条门路。
到此,问题失去解决。
能够看进去咱们定义一个递归类,比写一个递归函数的思路清晰的多。那么这样的递归类应该怎么构建呢。
构造函数的参数应包含如下几个:
public CurvesTree(List<Curve> curs, Curve cur0, Point3d point 底, CurvesTree father)
curs 是全族人,也就是所有的线,
cur0 是自己,
point 底是连贯父亲的点,
father 就是他的父亲树。
定义一个全族人的属性接管 curs,
赋值自己,
赋值脚,求出头(cur0 的另一个端点)。
如果是构建第一代先人,那么 father 就是 null。
依据 father 是否是 null,赋值父亲,赋值累计长度,赋值所有先辈。
而后要害的一步就是求所有的后辈。
咱们依据脚点,来找到所有端点重合的线。其中要删掉自己线。剩下的就是他的所有孩子们。
遍历这些孩子们,调用此构造函数自身。把 curs,孩子线,这个点,以及 this 作为 father,以上参数,递归此构造函数。于是就产生了一个递归的类。
递归函数的写法就是在函数外部调用函数自身,产生递归。而递归类就是在构造函数中调用构造函数自身,于是就产生了递归类。
咱们 new 这个类的时候,只有把树根的线作为自己线,父亲 null,来结构,就产生了一整个树。
之后再写几个办法,求所有的孩子,也是个递归办法。找到所有没有孩子的后辈,找到其中累计长度最大的,他的所有先辈加上他本人,就是由树根开始最长的一条门路。
以上就是这个问题的思路。
简略的说一下面向对象的编程思维。要晓得并不是你应用一个对象语言就叫做“面向对象”编程。面向对象编程是一种思维模式。和传统的面向过程的编程思维不同。传统的面向过程的编程思维,是着眼于一个过程。想解决一个问题,第一步要做什么,第二步要做什么,一步一步下来,整个的过程,就是面向过程的编程思路。当然在细节上咱们离不开过程,须要常常的思考程序过程。然而在整个程序的架构上,咱们须要面向对象。这样更容易让问题清晰,直指要害,轻松解决。什么是面向对象的思维模式呢?也就是当咱们面对一个问题,首先应该去设想一个事物,这个事物就是一个对象,他是活的。他有本人的共性,有本人的标签,有本人的做事格调。咱们形象出这样的一个对象进去,定义出他的类。设计他的属性,描述他的动作。就是他长什么样,他有什么动作。他的动作须要什么资料,能产生什么后果。这些是咱们思考的内容。这就是面向对象的编程思维。这也是一种思维模式。
了解一个过程可能是十分繁琐,凌乱的。而了解一个“事物”,往往很容易。就好比此题,如果咱们去设想这个迭代的整个过程,很可能会越想越迷糊。其中可能波及的很多细节问题会经常出错。而咱们把他看做是一棵树,或者一个家族树,一个族谱。那么很多问题就十分好了解了。如果细节上遇到了问题,咱们就能够减少一个属性来形容这个问题,减少一个办法来解决这个问题。而不是在一个微小的迭代函数里高低找来找去。闹的脑子一锅粥。一个好的程序往往就取决于你的类定义的是否优良。而一个好的程序员必须要具备面向对象的思维模式。这是最根本的。
附我的代码:(因为自己不是专业人士,代码语法写的很潦草,见谅,置信大家能看懂,不美观的中央本人批改吧。)
https://download.csdn.net/dow…