在这种情况下,我会说,理想的答案是,这取决于枚举是如何消费的,但在大多数情况下,它可能是最好单独定义的所有枚举,但如果任何人都已经通过设计加上,你应该提供一个集体介绍所述耦合枚举的方法。实际上,您的耦合公差最大为已经存在的有意耦合的数量,但没有更多。
考虑到这一点,最灵活的解决方案可能是在一个单独的文件中定义每个枚举,但在合理的情况下提供耦合的程序包(由相关枚举的预期用途确定)。
在同一文件中定义所有枚举会将它们耦合在一起,并且通过扩展使依赖一个或多个枚举的任何代码都依赖于所有枚举,而不管该代码是否实际使用任何其他枚举。
#include "enumList.h"
// Draw map texture. Requires map_t.
// Not responsible for rendering entities, so doesn't require other enums.
// Introduces two unnecessary couplings.
void renderMap(map_t, mapIndex);
renderMap()
宁愿只知道map_t
,因为否则对其他任何更改都会影响它,即使它实际上并未与其他对象交互。
#include "mapEnum.h" // Theoretical file defining map_t.
void renderMap(map_t, mapIndex);
但是,如果组件已经耦合在一起,则在单个封装中提供多个枚举可以轻松地提供更多的清晰度和简便性,只要有明确的逻辑理由将枚举耦合在一起,那么这些枚举的使用也应该耦合在一起,并且提供它们也不会引入任何其他耦合。
#include "entityEnum.h" // Theoretical file defining entity_t.
#include "materialsEnum.h" // Theoretical file defining materials_t.
// Can entity break the specified material?
bool canBreakMaterial(entity_t, materials_t);
在这种情况下,实体类型和材料类型之间没有直接的逻辑联系(假设实体不是由定义的材料之一构成的)。但是,如果遇到一种情况,例如,一个枚举明确地依赖于另一个枚举,则提供包含所有耦合枚举(以及任何其他耦合组件)的单个程序包是有意义的,这样耦合可以是尽可能合理地隔离到该程序包。
// File: "actionEnums.h"
enum action_t { ATTACK, DEFEND, SKILL, ITEM }; // Action type.
enum skill_t { DAMAGE, HEAL, BUFF, DEBUFF, INFLICT, NONE }; // Skill subtype.
// -----
#include "actionTypes.h" // Provides action_t & skill_t from "actionEnums.h", and class Action (which couples them).
#include "entityEnum.h" // Theoretical file defining entity_t.
// Assume ActFlags is or acts as a table of flags indicating what is and isn't allowable, based on entity_t and Action.
ImplementationDetail ActFlags;
// Indicate whether a given type of entity can perform the specified action type.
// Assume class Action provides members type() and subtype(), corresponding to action_t and skill_t respectively.
// Is only slightly aware of the coupling; knows type() and subtype() are coupled, but not how or why they're coupled.
bool canAct(entity_t e, const Action& act) {
return ActFlags[e][act.type()][act.subtype()];
}
但是可惜……即使两个枚举在本质上耦合在一起,即使它的强度与“第二枚举为第一枚枚举提供子类别”一样强,但有时仍然只有一个枚举是必要的。
#include "actionEnums.h"
// Indicates whether a skill can be used from the menu screen, based on the skill's type.
// Isn't concerned with other action types, thus doesn't need to be coupled to them.
bool skillUsableOnMenu(skill_t);
// -----
// Or...
// -----
#include "actionEnums.h"
#include "gameModeEnum.h" // Defines enum gameMode_t, which includes MENU, CUTSCENE, FIELD, and BATTLE.
// Used to grey out blocked actions types, and render them unselectable.
// All actions are blocked in cutscene, or allowed in battle/on field.
// Skill and item usage is allowed in menu. Individual skills will be checked on attempted use.
// Isn't concerned with specific types of skills, only with broad categories.
bool actionBlockedByGameMode(gameMode_t mode, action_t act) {
if (mode == CUTSCENE) { return true; }
if (mode == MENU) { return (act == SKILL || act == ITEM); }
//assert(mode == BATTLE || mode == FIELD);
return false;
}
因此,由于我们都知道,总是存在以下情况:在单个文件中定义多个枚举会增加不必要的耦合,并且在单个包中提供耦合的枚举可以阐明预期的用法,并允许我们将实际的耦合代码本身隔离为理想的解决方案是尽可能地分别定义每个枚举,并为打算经常一起使用的任何枚举提供联合程序包。在同一文件中定义的唯一枚举将是本质上链接在一起的枚举,因此使用一个枚举也必须使用另一个枚举。
// File: "materialsEnum.h"
enum materials_t { WOOD, STONE, ETC };
// -----
// File: "entityEnum.h"
enum entity_t { PLAYER, MONSTER };
// -----
// File: "mapEnum.h"
enum map_t { 2D, 3D };
// -----
// File: "actionTypesEnum.h"
enum action_t { ATTACK, DEFEND, SKILL, ITEM };
// -----
// File: "skillTypesEnum.h"
enum skill_t { DAMAGE, HEAL, BUFF, DEBUFF, INFLICT, NONE };
// -----
// File: "actionEnums.h"
#include "actionTypesEnum.h"
#include "skillTypesEnum.h"