面向对象是符合人类思考方式的。
1、面向对象的“整理归类”特性
①、面向对象的一个重要特性是将程序中出现的属性和方法整理归类。 理想/极限情况下,程序中所有属性和方法都能找到其所属类。
②、继承是更进一步的整理和归类,它将各个子类的相同属性和方法抽象到父类中,以此大量减少重复代码。
(仅为了减少重复代码而定义一个全局的Util类存放各种杂乱的方法是不好的,不要这么干)
(继承在一定程度上带来了耦合度和复杂度,仅为了减少少量重复代码而继承,可能得不偿失)
2、利用面向对象思想快速搭建游戏demo。
在面对一个游戏设计时,可以先大胆将游戏设计内容对象化(可画出类图)。然后在处理具体游戏业务的时,按照实际需求逐步将必需的属性和行为加入到对象中。
如下:(一个曾经快速搭建但未完成的demo类图)
3、UI 对象化设计制作。
每个界面作为一个游戏对象。界面中,较为独立的部分/重复出现的部分,可以单作为游戏对象。
逐层嵌套,形成父子关系。 聚合/组合关系:1~1或1~N。
这样做的好处是:
1、可以针对各层对象写逻辑,使逻辑各归其所。
2、对象可以复用。界面干净整洁、统一性好,不会出现有两处相同的东西,却长得不太一样。
3、极大加快UI开发效率,设计界面、拼界面、写界面逻辑都是对 “对象化的零件” 进行拼凑组合。
比如:商店界面:商店界面 -> 货架 -> 货架的层 -> 货架层上的物体。
比如:编队界面:编队界面 -> 队伍槽位 -> 队伍中的英雄。
比如:英雄培养界面:英雄培养界面 -> 消耗材料槽(放材料图标和拥有/需求数量) -> 材料图标。
要求:策划和美术要按照对象化的思想进行设计。
4、利用面向对象思想快速阅读他人代码/官方源码
5、游戏对象与数据结构与存档
简单来说,
游戏的初始化就是:将存档的数据包反序列化为数据结构,然后一层层还原为游戏对象。
游戏的进行就是:玩家通过操作改变游戏对象的属性。
游戏的存档就是:将游戏对象一层一层提纯为数据结构,然后序列化为数据包,然后存档。
6、面向对象与策划表
① 、 “在列首定义表头字段、按行填值” 的excel,本身就是对象化的。
表头字段可看作类的字段,每行的数据都是类的对象。只是这个类只有字段,没有方法(Excel中也定义不了方法)。
准确地说,策划表中每行数据形成的对象只是其对应的游戏对象的一部分(partial),因为它只是静态数据,实际的游戏对象应由静态数据和动态数据共同组成(但不是绝对的)。
②、按继承关系拆分策划表。
在实际开发中发现,一个复杂的表结构,很难平铺在一张表中(如,活动表)。
强行平铺可能导致大量字段冗余,填表的人在填写时会懵逼(???到底哪些列填了是生效的),也容易填错。(如,A类型活动需要MXYZEF字段,B类型活动需要MXYZGH字段(M为主键))
这种情况就应该拆分为父子表。不同类型的对象单独建立子表,子表的第一主键索指向父表。
父表只配公共部分的字段,子表中只配具体类型对象需要的字段。
(活动表拆分后:父表配 MXYZ字段,A类型活动子表配MEF字段、B类型活动子表配MGH字段)
③、按组合/聚合关系拆分策划表。
后来又发现,某活动除了有活动自身的配置(活动主图Spine、界面特效、关联某商店、整体奖励领取条件等),还拥有一个任务列表,而每个任务项都需要配置(任务序号索引、任务目标、跳转等)。很明显,该活动与任务项的关系是 聚合。
这种情况应该增加一个 “聚合子表”。
(假设该活动还是②中的A活动,增加后,父表配 MXYZ字段,A类型活动子表配MEF字段,A类型活动的任务表配MNJK字段(N是任务序号索引,为第二主键))。
(如果该活动只有任务列表的配置,则为组合关系,没有自身的配置,可直接省略A类型活动子表)
---------------------------- NRatel割 ----------------------------
一般情况下,表拆三层足够满足大多数需求。
表拆得更细,逻辑会更清晰,但维护起来会变得麻烦,策划可能不会接受。
简单的需求,也可以适当允许字段冗余而不拆分表。
7、纯粹面向对象的问题
当对象行为复杂时,可能难以抽象表述为继承关系,因此也无法让代码复用。
如:
①,菱形继承的问题 类B、C继承自类A, 类D 又希望同时拥有类BC的行为。
②,有类 A、B、C 和 行为 X、Y、Z,其中,
类 A 拥有行为 XY,
类 B 拥有行为 XYZ,
类 C 拥有行为 YZ,
这种情况下,虽然它们之间有公共方法,但却无法干净地抽象出公共父类。
8、面向接口
①、面向接口是对面向对象的补充,它从整体出发,定义了各系统/模块之间的交互规范。
②、可以通过实现一组接口,快速拓展出适用于设计体系的模块。
③、实现接口的模块,要完成接口定义的、对外提供的功能。
④、调用接口的模块,不关心接口实现者的内部实现。
⑤、面向接口可能造成重复代码,但这在整体架构面前可能微不足道。 (重复原因:原本属于各个子类的方法,变成了属于规范。没办法再通过“抽象出父类”的办法消除重复了)。
⑥、为了解决接口实现的代码重复问题,C#8.0中又允许接口定义默认方法。
⑦、定义一个接口帮助类,也可解决接口实现的代码重复问题。
public interface IProgress
{
int GetCurCount();
int GetMaxCount();
}
public static class IProgressHelper
{
public static float GetProgress(this IProgress p)
{
return (float)p.GetCurCount() / p.GetMaxCount();
}
}