gpt4 book ai didi

c++ - 复合类 C++ 中的冗余代码

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:03:54 25 4
gpt4 key购买 nike

我正在尝试学习 C++。一切都很顺利,直到我的“练习”程序遇到了很小的障碍。我认为,这种障碍源于设计问题。

想想二十一点 (21)。我上了几节课。

  1. 名片
  2. 甲板
  3. 播放器

为了简单起见,一副牌包含一系列卡片。
-它可以显示所有卡片
-可以随机播放
-可以取卡

A Hand Is A Deck - 受益于
-它可以计算它的手牌值(value)
-可以给手牌加牌

现在开始我的问题 - 播放器设计

-A Player Has A hand(私有(private)访问)
我的播放器问题是手有一个名为addCardToHand 的方法函数。如果我必须创建一个名为 addCardToHand(Card c) 的 Player 方法,在其中调用并传递给手头的相同方法,我会感到冗余/糟糕的设计。

将 Hand h 声明为可公开访问的成员,并在“main()”中执行类似
玩家p;
卡片aCard;
p.h.addCard(aCard);

任何建议都会很有启发性并受到高度赞赏。请记住,我正在学习。

最佳答案

这里的最佳答案是:这取决于 :) 不过,我会尝试稍微澄清一下。

第一个问题是:Player类有没有内在逻辑?如果它是 Hand 的简单容器,我会简单地写 Player.GetHand().AddCard() ,因为没有理由复制 Player.AddCard() 中的代码方法,问题解决。

现在让我们假设,需要实现额外的逻辑来将牌添加到玩家的手上。这意味着,在向 Hand 添加卡片时必须调用 Player 类中的附加代码。在这种情况下,我看到三种可能的解决方案。

(源仅用于演示目的,可能无法编译)

  • 限制对 Hand 的访问,这样就没有人可以从 Player 那里取回它。 Player 必须实现 AddToHand、RemoveFromHand 等方法。可行,但使用起来不舒服。

    class Player
    {
    private:
    Hand hand;

    public:
    void AddToHand(Card & card)
    {
    hand.Add(card);
    }
    };
  • 使用 observer pattern .当用户(类用户)调用 Player.GetHand().AddCard() 时,Hand 通知 Player,数据已更改,Player 可以相应地进行操作。使用 C++11 中的 std::function 来实现事件,您可以很容易地实现这一点。

    class Deck
    {
    private:
    std::function<void(void)> cardsChanged;

    public:
    void Add(Card card)
    {
    // Add a card
    if (!(cardsChanged._Empty()))
    cardsChanged();
    }

    void SetCardsChangedHandler(std::function<void(void)> newHandler)
    {
    cardsChanged = newHandler;
    }
    };

    // (...)

    class Player
    {
    private:
    Hand hand;

    void CardsChanged() { ... }
    (...)
    public:
    Player()
    {
    hand.SetCardsChangedHandler([&this]() { this.CardsChanged(); } );
    }
    };
  • 使用所有必要的接口(interface)方法定义 IHand 接口(interface)。 Hand 显然应该实现 IHand,Player.GetHand() 应该返回 IHand。诀窍在于,Player 返回的 IHand 不一定是 Hand 实例,而是它可以是一个装饰器,充当用户和真实 Hand 实例之间的桥梁(参见 decorator pattern )。

    class IHand
    {
    public:
    virtual void Add(Card card) = 0;
    virtual void Remove(Card card) = 0;
    };

    class Hand : public IHand
    {
    // Implementations
    }

    class PlayersHand : public IHand
    {
    private:
    Hand & hand;
    Player & player;

    public:
    PlayersHand(Hand & newHand, Player & newPlayer)
    {
    hand = newHand;
    player = newPlayer;
    }

    void Add(Card card)
    {
    hand.Add(card);
    player.HandChanged();
    }

    // ...
    };

    class Player
    {
    private:
    Hand hand;
    PlayersHand * playersHand;

    public:
    Player()
    {
    playersHand = new PlayersHand(hand, this);
    }

    IHand GetHand()
    {
    return playersHand;
    }
    }

就个人而言,在第二种情况下,我会选择第二种解决方案 - 它非常简单且易于扩展和重用,以备不时之需。

关于c++ - 复合类 C++ 中的冗余代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14666353/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com