αναίρεση της επαναφοράς με ένα μηχανισμό αυτόματης διαγράψετε

ψήφοι
0

Η εφαρμογή μου είναι αναπτυχθεί σε C ++ με χρήση Qt και χρησιμοποιεί τα σήματα και τις αυλακώσεις.

Ας πούμε ότι έχω τις ακόλουθες κατηγορίες (ψευδο-C ++ κώδικα):

class Ball
{
    Color m_Color;
    int m_Size;
};

class Player
{
public:
    setBall(Ball* pBall)
    {
        if (pBall != m_pBall)
        {
            Ball* pPreviousBall = m_pBall;
            m_pBall = pBall;
            emit notifyBallNotUsed(pPreviousBall);
        }
    }

    Ball* getBall();

signals:
    void notifyBallNotUsed(Ball*);

private:
    String m_Name;
    Ball* m_pBall;
};

class GeneralHandler
{
public:
    addBall(Ball* pBall);
    deleteBall(Ball* pBall);


    addPlayer(Player* pPlayer)
    {
        connect(pPlayer, SIGNAL(notifyBallNotUsed(Ball*)), this, SLOT(onBallUsageChanged(Ball*)));
        ...
    }
    deletePlayer(Player* pPlayer);
    {
        disconnect(pPlayer, SIGNAL(notifyBallNotUsed(Ball*)), this, SLOT(onBallUsageChanged(Ball*)));

        onBallUsageChanged(pPlayer->getBall());
        ....
    }

private slots:
    void onBallUsageChanged(Ball* pBall)
    {
        if (isNotUsedAnymore(pBall))
        {
            m_BallList.remove(pBall);
            delete pBall;
        }
    }

private:
    bool isNotUsedAnymore(Ball* pBall); // Check if the given ball is still used by at least one player

    List<Player*> m_PlayerList;
    List<Ball*> m_BallList;
};

Με την αίτησή μου, ο χρήστης μπορεί να προσθέσει / αφαιρέσει player, καθώς και για κάθε παίκτη, να αποφασίσει το χρώμα και το μέγεθος της μπάλας. Πίσω από την κουκούλα, το GeneralHandler είναι υπεύθυνος για την αποθήκευση τις μπάλες και να τους διαγράψετε. Είναι πολύ πιθανό ότι οι δύο παίκτες χρησιμοποιούν την ίδια μπάλα.

Όταν ένας παίκτης έχει διαγραφεί, αν η μπάλα δεν χρησιμοποιείται πια, η GeneralHandler πρέπει να το διαγράψετε (ή κρατήστε το αν η μπάλα εξακολουθεί να χρησιμοποιείται από έναν άλλο παίκτη). Εάν η μπάλα ένας παίκτης χρησιμοποιεί αλλάξει, η προηγούμενη μπάλα, αν δεν χρησιμοποιούνται πια, θα πρέπει να διαγραφεί από το GeneralHandler επίσης.

Μέχρι εδώ καλά.

Τώρα, θέλω να προσθέσω δυνατότητα undo / redo με την αίτησή μου, χρησιμοποιώντας το πρότυπο διοίκησης, και αυτό είναι που είμαι κολλημένος. Αφήνει να πω ότι έχω κάτι σαν αυτό:

class ChangePlayerBall : public QUndoCommand
{
public:
    ChangePlayerBall(Player* pPlayer, Ball* pNewBall)
    {
        m_pPlayer = pPlayer;
    }

    void redo();
    void undo();

private:
    Player* m_pPlayer;
};

Υποθέτω ότι η μέθοδος ξανακάνω () θα μοιάζει κάπως έτσι:

void ChangePlayerBall::redo()
{
    m_pPlayer->setBall(pNewBall);
}

Αν μη τι άλλο έχει αλλάξει στον παραπάνω κώδικα, η προηγούμενη Ball θα διαγραφεί εάν δεν χρησιμοποιούνται πια από τους άλλους παίκτες. Αυτό θα είναι ένα πρόβλημα κατά την εφαρμογή της μεθόδου αναίρεσης (): εάν έχει διαγραφεί η προηγούμενη μπάλα, δεν ξέρω τι ήταν αυτό είναι τα χαρακτηριστικά και η εντολή αναίρεσης δεν θα είναι σε θέση να αναδημιουργήσει. Ή ίσως θα πρέπει να αποθηκεύσετε το προηγούμενο μπάλα, αλλά πώς θα ξέρει την εντολή Undo / Redo αν αυτό προηγούμενα μπάλα εξακολουθεί να είναι υφιστάμενες ή έχει διαγραφεί από τον χειριστή; Ή ίσως αυτός ο μηχανισμός της διαγραφής μια μπάλα από τη στιγμή που δεν χρησιμοποιείται πλέον θα πρέπει να εφαρμοστεί στην εντολή αναίρεσης; Το πρόβλημα είναι ότι η εντολή αναίρεσης θα έχουν πολλές εξαρτήσεις σε πολλές άλλες κατηγορίες. Το άλλο πρόβλημα είναι ότι αυτός ο κώδικας θα αντιγραφεί εν μέρει στην εντολή DeletePlayer, η οποία θα πρέπει να κάνει κάτι παρόμοιο:

class DeletePlayer : public QUndoCommand
{
public:
    DeletePlayer(Player* pPlayer);

    void redo();
    void undo();
...
};

Ελπίζω explainations μου, όπου κατανοητό!

Πώς θα λύσουμε αυτό το πρόβλημα; Δεν μπορώ να βρω μια ικανοποιητική λύση.

Ευχαριστώ !

Δημοσιεύθηκε 09/12/2008 στις 14:50
πηγή χρήστη
Σε άλλες γλώσσες...                            


3 απαντήσεις

ψήφοι
1

Μπάλα θα διαγραφεί εάν δεν χρησιμοποιούνται πια από τους άλλους παίκτες

Όπως μπορώ να δω - είναι s the source of your doubts. Certainly undo() command shouldn't recreate an object nor have itδική του μηχανισμού διαγραφής. Πώς GeneralHandler.isNotUsedAnymore σας () λειτουργεί; Αν μετράει αναφορές σε μπάλες, από αναφορά στην περίπτωση της ChangePlayerBall θα πρέπει επίσης να υπολογίζονται. Ως εκ τούτου, θα πρέπει να συνδεθείτε αντικείμενο εντολών σε ορισμένες GeneralHandler`s υποδοχές.

Έτσι, εγώ θα πρότεινα:

  1. Μπάλα διαγράφεται όταν `s δεν χρησιμοποιείται με οποιοδήποτε παίκτες και τυχόν UndoCommands (μπορεί να συμπεριλαμβανομένης της αλλαγής του χρώματος & κλπ)
  2. Σύνδεση μεταξύ μπάλα και παίκτη φρένα σε νέα ανάθεση μπάλα ως `ve γίνει
  3. Σύνδεση μεταξύ μπάλα και εντολών φρένα σε command`s αντικείμενο destructor (όταν αφαιρεθεί εντελώς από τη στοίβα)

Η ελπίδα αυτό βοηθά)

Απαντήθηκε 16/12/2008 στις 10:08
πηγή χρήστη

ψήφοι
0
  1. Αποθηκεύστε μπάλα κατασκευαστή εντολή του.
  2. Βάλτε το in / out όποτε χρειάζεται.
  3. Χρησιμοποιήστε QSharedPointer για την μπάλα παντού για την αποφυγή διαρροών μνήμης.
Απαντήθηκε 01/12/2010 στις 09:12
πηγή χρήστη

ψήφοι
0

Πόσο περίπου χρησιμοποιώντας ένα τέχνασμα μέτρησης αναφοράς για την μπάλα; Όταν μια μπάλα αποθηκεύεται στην εντολή, η εντολή μπορεί να αυξήσει τον αριθμό αναφοράς για την μπάλα, εμποδίζοντας έτσι τη διαγραφή από το χειριστή (ή από μόνη της, ανάλογα με το πώς θα άλλαζε την εφαρμογή).

Απαντήθηκε 28/05/2009 στις 21:26
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more