Ваша базовая идея верна, но вы должны улучшить ее, чтобы сохранить высокий уровень абстракции и инкапсуляции.
Итак, в вашем примере, скажем, у вас есть класс Card
, который является экземпляром существующегокласс.
Первое, что вы можете сделать, это отделить эффект карты от самой карты, например:
class CardEffect {
// TODO ...
};
class Card {
private:
const CardEffect* effect;
};
Так что теперь самой карте не нужно знатьчто-нибудь об игре.Но давайте углубимся в это: CardEffect
не нужно знать каждую деталь класса Game
, он должен уметь применять эффекты к игре.Это можно сделать, предоставив отдельный интерфейс с эффектом, который показывает только то, что необходимо для применения эффекта, и что-то вроде этого.
class GameInterface {
public:
virtual const std::vector<Player*>& getPlayers() = 0;
virtual damagePlayer(Player* player, int amount) = 0;
virtual applyPeriodicDamage(Player* player, int turns, int amount) = 0
..
};
class CardEffect {
virtual applyEffect(GameInterface* interface) = 0;
};
class Card {
private:
const CardEffect* effect;
};
Теперь это только пример, окончательного решения вашей проблемы не существует.поскольку каждый конкретный сценарий отличается от других и предъявляет различные требования, это просто дает вам базовую идею о том, как можно сохранить элегантность и инкапсуляцию кода, в то же время оставляя его достаточно наглядным, чтобы им было легко управлять.