单身对于纸牌游戏中的可见状态类是一个好主意吗?

时间:2014-02-19 18:06:37

标签: objective-c class singleton

我正在写一个Objective-C的纸牌游戏,我比较陌生(我根本没有很多编程经验)。我有一个很多对象需要访问的 VisibleState 类。在游戏中,当然只能有一个可见状态,这意味着拥有该类的多个实例是没有意义的。

这是 VisibleState 类应该是单例类的情况吗?我做了一些研究,许多网站都说当只有一个类的实例存在时,它可以是一个单例类。但是,我还读过单身模式经常被误用,应该避免。这个可见的状态类应该是单例还是应该是常规状态?

修改

纸牌游戏目前是用C ++编写的。我提前问过这个问题,因为我计划在Objective-C中重写它,并希望比上次更好地构建类。

编辑2

// VisibleState.h

struct PublicPlayerInfo
{
    unsigned short m_unNumberOfHandCards = 0;
    unsigned short m_unNumberOfVisibleCards = 0;
    unsigned short m_unNumberOfHiddenCards = 0;
    Card m_acVisibleCards[3];
    Cardstack* m_pcPlayerHand = 0;

    bool m_bHasWon = false;
    std::string m_strName = "";
};

struct PublicTableInfo
{
    unsigned short m_unNumberOfTableCards = 0;
    unsigned short m_unNumberOfDrawCards = 0;
    unsigned short m_unNumberOfShitCards = 0;
    Card m_cTopCard;
};

struct VisibleState
{
    std::vector<PublicPlayerInfo> m_vecPublicPlayerInfo;
    PublicTableInfo m_sPublicTableInfo;
    unsigned short m_unCurrentPlayerNumber = 0;
};

// Player.h (only relevant code)

class Player
{
private:
    Cardstack m_cHand;
    Cardstack m_cVisible;
    Cardstack m_cHidden;
    const std::string m_strName;
    const Difficulty m_eDifficulty;
    const unsigned short m_unPlayerNumber;

    static FrontEnd* s_pcGUI;
    static AI* s_pcAI;
    static VisibleState* s_psVisibleState;
}; // Irrelevant code exlcuded


// Player.cpp

// I only took the simplest example function, if I would post all code, over five hundered lines would be used

Card Player::LayHandCard(const Card& rcCurrentTableCard, noc& runNumberOfCards)

{
    Card cLaidHandCard;
    noc unNumberOfCards;

    switch (m_eDifficulty)
    {
        case PERSON:
            cLaidHandCard = m_cHand.Take(s_pcGUI->LayHandCard(m_cHand, rcCurrentTableCard, unNumberOfCards));
            break;
        case LEVEL1:
            cLaidHandCard = m_cHand.Take(s_pcAI->Lv1_LayHandCard(m_cHand, rcCurrentTableCard, unNumberOfCards));
            break;
        case LEVEL2:
            cLaidHandCard = m_cHand.Take(s_pcAI->Lv2_LayHandCard(m_cHand, rcCurrentTableCard, unNumberOfCards));
            break;
        case LEVEL3:
            cLaidHandCard = m_cHand.Take(s_pcAI->Lv3_LayHandCard(m_cHand, rcCurrentTableCard, unNumberOfCards));
            break;
        case LEVEL4:
            cLaidHandCard = m_cHand.Take(s_pcAI->Lv4_LayHandCard(m_cHand, rcCurrentTableCard, unNumberOfCards));
            break;
        case LEVEL5:
            cLaidHandCard = m_cHand.Take(s_pcAI->Lv5_LayHandCard(m_cHand, rcCurrentTableCard, unNumberOfCards));
            break;
    }

    noc unNumberOfCardsLeft = unNumberOfCards;
    noc unNumberOfCardsLaid = 0;

    if (unNumberOfCardsLeft == 0)   // 0 means lay all, so a silly amount of checks must be done
        unNumberOfCardsLeft = 30000;
    else
        unNumberOfCardsLeft--;      // If 1 or more, it means that a special amount of cards will be taken, but one is already taken above
    unNumberOfCardsLaid++;

    for (noc unCurrentIndex = 0; unCurrentIndex < m_cHand.CountCards() && unNumberOfCardsLeft > 0; unCurrentIndex++)
    {
        if (m_cHand.Read(unCurrentIndex) == cLaidHandCard)
        {
            m_cHand.Take(unCurrentIndex);
            unNumberOfCardsLeft--;
            unNumberOfCardsLaid++;
        }
    }

    s_psVisibleState->m_vecPublicPlayerInfo[m_unPlayerNumber].m_unNumberOfHandCards -= unNumberOfCardsLaid;

    runNumberOfCards = unNumberOfCardsLaid;
    return cLaidHandCard;
}

编辑3

如果有帮助,这是一个类结构的图片:

2 个答案:

答案 0 :(得分:1)

  

我有一个VisibleState类,许多对象需要访问...我还读过单例模式经常被滥用

如果你的动机是:“我需要从很多不同的地方访问这个对象,你会滥用这个模式,如果我只是把它变成单身,那就太容易了,因为那样我就可以使用全局存取器从任何地方获取物体。“由于您不熟悉编程,因此为什么这可能不是很明显。以下是思维创造的两个问题:

  1. 您将自己锁定在关于如何使用此类的假设中,并且可能在某些时候无效。您现在可能只需要一个VisibleState实例,但在一两个月内为游戏添加多人游戏功能时,可能需要两个或更多实例。也许你想要在游戏中的不同点保存快照,只需复制当前的可见状态就可以轻松实现。不要混淆“我只需要一个”和“绝不能超过一个。”

  2. 当您可以从程序中的任何位置轻松访问单个对象时,程序的任何部分都可以更改该对象。这通常是全局变量的问题,并且使用单例因为它易于从任何地方访问意味着单例对象与全局变量基本相同。当另一部分不期望它改变时,由程序的一部分改变对象引起的错误可能难以重现,难以找到并且难以修复。

  3. 很多人使用和滥用单身人士会告诉你所有批评都被夸大了,事情会好起来等等。有一些事实 - 你可以用单身人士编写一个完全可用的程序,并可能保存自己一段时间。您可能不关心未来的灵活性,并且您可能愿意承诺永远不会有多个VisibleState的实例。请记住,使用单例进行全局访问是一种快捷方式,就像其他快捷方式一样,它可以很好地工作,也可以咬你。你说你“比上一次更好地构建了类”,所以听起来你最好不要只考虑你的对象与对方之间的关系,而是采取简单的方法。

答案 1 :(得分:0)

老实说,看起来你的课程结构过于复杂。你应该有桌子,球员和牌桌。可见应该是卡的属性,而不是自己的类。如果任何东西都是单身,它应该是桌子。如果没有看到代码,很难给出确切的答案。