面向对象的程序设计在游戏开发中使用(四):五大原则

作者:Kingfeng 奶牛关 2019-08-14


我们已经提过了三大特性。而真正再使用中,我们更多的会基于五大原则来设计,不用担心,和之前的文章相似,我会尽量使用更加通俗的语言来表述,而非实际针对语言如何完成。

另外,我发现并没有实例进行说明,但是这并不是很复杂的内容。

一个类是一种概念,而当我们需要根据这种概念创造一个属于这种概念的实际存在时,我们吧这种操作称作实例化,就像吧橡皮泥按压到模具中。而所创建的就是实例。

1单一职责原则

单一职责本质上是公鸡要下蛋的问题。对于一个类,他所实现的功能应该仅限于他的职权范围内。

打印一份材料,我们吧打印交给打印机。对于常识意义上的打印机,虽然很方便,但是我们真的不需要也不应该给打印机加入装订和裁纸的功能,而是应该单独制作装订器类和裁纸刀类。就像游戏里的子弹,在它们打到人的时候,这个伤害计算显然不应该交给子弹来计算,也不应该交给玩家来计算,在实际使用的过程中,我更倾向于编写一个伤害类,每当造成伤害后,创造一个伤害类的实例,进行计算。

对于一个简单的【攻击并受伤】的环境下,我们可以创建通过简单的血量变化达到这个目的。但如果期望的是一个更加复杂的伤害系统,将伤害单独分离出来是很明智的。

这也就是所谓的单一指责,一个类只有一个职责,只负责自己范围内的工作。

2开放封闭原则

对于一个类,应该是可扩展,但是不可修改的。

在我们编写代码,使用这个类时,我们需要对其进行功能上需求的变更,我们应当对其进行扩展,而不是直接的修改原有的代码。

这么做显然是昂贵的,会浪费大量的时间和精力在将概念抽象化。

因此在实际编写时,先从核心的、稳定的、不易改变的部分下手,抽象化那些已经明确复杂、难以控制的部分。

同时,在后续编写中,如果发生了意外变化再将那些变化隔离进行扩展。

同样,编写测试是十分重要的,对于那些难以控制、不稳定的逻辑或数值上的部分,将其设计在单独的代码中,并编写测试。

3里氏替换原则

虽然名字并不是那么直接,但是实际上之前的文章已经提到过这个原则。

也就是子类应该透明的替换父类。

如果我们有一个图形类,他的子类有正方形圆形等等。

假如我们吧一个正方形,作为一个图形类传递到函数中,在里氏替换原则下,我们的程序不应该出现类型不匹配的问题。对于不同的语言,有不同的处理方法。但是这一点是我们在设计时需要注意的。

这种关系在很多时候被称作IS-A关系,而就如字面意思所说,白马是马,黑马也是马。

我们在程序设计时,就应当从这种角度来出发明确类和子类的关系。

这条主要是说明了类之间的关系,怎样处理这种关系。

在设计时可以通过遵循契约设计来达到这种效果

遵循契约设计原则

这里的契约更像是一种约定,或者一种操作界面。这种契约在类的某一个实例实际使用时交互时被遵守。这种契约简单的说包含两个部分,对于父类可接受的一切子类必须接受,父类的用户不能受到子类的干扰。

这就好比一个契约,对于母公司与客户所签署的契约,子公司/分公司应该与母公司一样遵守契约。同样的,对于这份契约,客户使用这个契约与子公司进行交流时应该与母公司没有差异。

在编程里,如果需要对类进行扩展,使用函数覆盖父类的相应函数,那么这种扩展不应该是针对功能的,而应只改变内部的处理方式和流程,就像是一加一,你可以吧1+1=2用1+1=3覆盖,他们只是处理的流程和方式不同,但是1+1=a会对客户的使用造成困扰,因为这没有遵守契约。

4依赖倒置原则

一台电脑由零件组成,有硬盘有显卡。那么我们是怎么把他们拼装到一起的呢?

对于硬盘,我们有SATA接口,当然也有M2接口。而显卡,我们把他插在PCI上。同时,PCI也可以插网卡。

这些接口保证了我们可以自由插拔各种外界设备。而在程序编程中,我们同样有类似的方法可以使得这种自由的插拔合理的应用在我们的代码当中。

首先,依赖本身,表示高层模块由底层模块构成,高层模块依赖着这些底层模块,这很合理。当我们写字,就调用笔的写字方法,我们已经说过这一点了。

但是实际上,这种依赖会导致一些问题,我们学会使用所有的笔写字,但是钥匙在纸上也可以划出痕迹,石块在地面上也存在白色的划痕,甚至我们会在压敏纸上用指甲记录电话号码。

而这就要求我们在处理大的庞大的交互中,使用依赖倒置原则。

也就是,高层不应依赖底层,两者共同依赖抽象。

我们再来看看上述例子,想想我们是如何做到的。

在成长和教育的过程中,我们已经学会了写字,但是这种写字并不是用笔写,而是对写字这种抽象过程的能力。当我们用在编程当中,两件事物之间的依赖关系就不存在了,而是通过一种抽象的概念将两者联系在一起,而实现方法,在遵循抽象的功能上,根据需求而修改。

这在设计过程中保证了通用性,我们在设计笔时,将笔设计为抽象上的笔,在使用时作为使用者,使用抽象的【笔】就可以完成目的。而在实际制作各种各样的笔,同样引用抽象的笔并根据这种抽象所规划的,针对相应的功能更改具体实现方式。

之前我对此描述的时父类和子类的关系,但是实际上使用,这种抽象的概念更加的自由,我们设计了各种各样的抽象,而一个类选择数种抽象来实现其细节。

5接口隔离原则

上文所说这种抽象在硬件层面上则更像是接口,而接口隔离,则是细节上的如何规划这种接口。

笔有墨水,但是我们不能强迫每个笔都有墨水,在编程过程中,相比于单个、功能强大的接口,更希望拥有多个、功能单一、灵活的接口。

系列文章
面向对象的程序设计在游戏开发中使用(一):类
面向对象的程序设计在游戏开发中使用(二):方法
面向对象的程序设计在游戏开发中使用(三):三大特性
面向对象的程序设计在游戏开发中使用(四):五大原则

面向对象的程序设计在游戏开发中使用(五):基本计算器
面向对象的程序设计在游戏开发中使用(六):数与抽象数

面向对象的程序设计在游戏开发中使用(七):享受劳动果实

作者:Kingfeng

来源:奶牛关
原地址:https://cowlevel.net/article/2051883

最新评论
暂无评论
参与评论

商务合作 查看更多

编辑推荐 查看更多