Исходный код этой игры с открытым исходным кодом, поэтому я решил проверить его. В нем я нашел что-то вроде:
// This ActionManager is basically a controller like in the MVC pattern.
void ActionManager::HandleQueryMessage(csString xml, Client* client)
{
//check the two hands as a start.
psItem* item = client->GetCharacterData()->Inventory().GetInventoryItem(PSCHARACTER_SLOT_RIGHTHAND);
if(!item || !item->GetItemCommand().Length())
item = client->GetCharacterData()->Inventory().GetInventoryItem(PSCHARACTER_SLOT_LEFTHAND);
}
Первая строка для получения предмета явно нарушает закон Деметры. Однако, даже если он был изменен на client->GetCharacterData()->GetInventoryItem(PSCHARACTER_SLOT_RIGHTHAND);
, это все равно нарушило бы закон Деметры (насколько я знаю).
Что с этим можно сделать? или это одно из тех мест, где LOD не применяется [как в моем втором примере]?
Перемещение GetInventoryItem
вверх к client
класс не имеет смысла с моей точки зрения, так как клиент не имеет ничего общего с character
,
Создание оберток в client
класс для всех методов хх character
класс кажется излишним.
Какие-нибудь мысли?
Как вы предполагаете, если вы хотите полностью следовать LOD, вам понадобятся такие функции, как …
Item* Client::GetCharacterInventoryItem(int itemID)
{
return characterData->getInventoryItem(itemId);
}
/* ... */
Item* CharacterData::getInventoryItem(int itemID)
{
return inventory->getItem(itemId)
}
/* ... */
Item* Inventory::getItem(int itemID)
{
assert_valid_itemID(itemID);
return inventory_table[itemId];
}
Стоит ли эта дополнительная косвенность? Я не знаю, это зависит от конкретного случая, ваших личных предпочтений и т. Д. Как отмечается в комментариях, LOD следует рассматривать как руководство, а не как закон. С другой стороны, по моему личному опыту, ломайте его часто, и вы попадете в беду … 🙂
Других решений пока нет …