2010-08-10 14 views
2

J'ai quelques actions ... Afficher, éditer, vérifier, etc. La logique métier impose que si un document est déjà extrait, toutes les vues se transforment en éditions.une instance hot-swapping lui-même avec une nouvelle instance

est-il un moyen OO propre à faire quelque chose comme ceci:

class Action 
{ 
public: 
    Document document; 
    virtual void execute(); 
}; 
class View, Edit, Checkout : public Action; 

View::execute() 
{ 
    if (document.isCheckedOut) 
    { 
    delete this; 
    this = new Edit; 
    this->execute(); 
    } 
    /* execute view */ 
} 

mise à jour: ce que vous en pensez de ceci:

class Action 
{ 
public: 
    static int type; 
    Document document; 
    virtual void execute(); 
    static Action* construct(int type, Document document) = 0; 
private: 
    Action(); 
}; 
class View, Edit: public Action; 

Action* View::construct(Document document) 
{ 
    if (document.isCheckedOut) 
    return new Edit(document); 
    return new View(document); 
} 

Action* Edit::construct(Document document) 
{ 
    return new Edit(document); 
} 

void onViewButton(Document document) 
{ 
    Action *action = View::construct(document); 
    action->execute(); 
    delete action; 
} 
+1

Mieux vaut indiquer le problème que cela tente de résoudre. –

+0

Vous voudrez peut-être vérifier si certains des modèles bien connus comme Proxy (http://www.mindspring.com/~mgrand/pattern_synopses.htm#Proxy), Interface, Delegate; répondre à vos besoins, avant d'essayer de faire autre chose. – Ismael

+0

Pourquoi ne pas passer par où toutes les 'Actions 'sont stockées, et remplacer toutes les' View' par 'Edit'? Ou quelque chose. Il est difficile de comprendre ce que vous faites. – GManNickG

Répondre

1

Il n'y a pas moyen de réattribuer le « ceci Pointeur comme ça. Vous pouvez utiliser une implémentation de pointeur intelligent pour faire quelque chose de similaire en ajoutant une couche d'indirection.

class action_ptr 
{ 
    Action* m_Data; 
public: 
    action_ptr(Action* value) 
    { 
    m_Data = value; 
    } 

    Action* operator->() 
    { 
     if(m_Data->isView() && m_Data->isCheckedOut()) 
     { 
     delete m_Data; 
     m_Data = new Edit(); 
     } 
     return m_Data; 
    } 
}; 


// usage 
action_ptr pAction(new View()); 
pAction->DoViewStuff(); 
pAction->Checkout(); 
pAction->OtherStuff(); // If isCheckedOut returned true, this now magically operates on an Edit instead! 

C'est nullement censé être une mise en œuvre complète, simplement un exemple - il y a des fuites de mémoire et de nombreuses fonctions manquantes.

+0

Il pourrait être plus logique de considérer cela comme un modèle Pimpl dans lequel l'objet d'implémentation est remplacé en réponse à certaines conditions, plutôt que de l'appeler un pointeur intelligent. Mais le résultat final est similaire dans les deux cas. – TheUndeadFish

+0

Veuillez utiliser 'boost :: scoped_ptr ' ou 'std :: unique_ptr ' au lieu d'une simple 'Action *', de cette façon vous éviterez les fuites de mémoire flagrantes. –

0

Je résoudrais probablement cela avec le modèle de stratégie, où les stratégies ont une fonction de membre de conversion. Quelque chose le long de ces lignes (parties de code sans intérêt omis):

struct action_strategy { 
    virtual ~action_strategy(); 

    virtual action_strategy *convert_strategy(document const &doc); 
    virtual void execute() = 0; 
}; 

class action { // Hur, hur :D 
public: 
    // construct with heap-allocated strategy 
    action(action_strategy *strategy); 

    void execute() { 
    strategy_.reset(strategy_->convert_strategy(doc_); 
    strategy_->execute(); 
    } 

private: 
    document doc_; 
    std::auto_ptr<action_strategy> strategy_; 
}; 

// Default: do nothing 
action_strategy *action_strategy::convert_strategy(document const &doc) { 
    return this; 
} 

class view : public action_strategy { 
    // overload as necessary 
    virtual action_strategy *convert_strategy(document const &doc); 
}; 

action_strategy *view::convert_strategy(document const &doc) { 
    if(doc.is_checked_out()) { 
    return new edit(); 
    } 

    return this; 
}