Lo stesso Memento Pattern sembra piuttosto semplice. Sto considerando di implementare lo stesso come l'esempio di wikipedia, ma prima di farlo ci sono caratteristiche linguistiche di C# che rendono più facile l'implementazione o l'utilizzo?Come è implementato il Memento Pattern in C# 4?
risposta
Una caratteristica ovvia sarebbe generici, l'implementazione di un ricordo generico ti consentirà di utilizzarlo per qualsiasi oggetto desideri.
Molti esempi che vedrete utilizzeranno una stringa (compresi tutti quelli attualmente tra le risposte a questa domanda) come stato che è un problema poiché è uno dei pochi tipi in .NET che sono immutable.
Quando si tratta di oggetti mutabili (come qualsiasi tipo di riferimento con una proprietà di setter) è necessario ricordare che quando si salva il ricordo è necessario creare una copia dell'oggetto. Altrimenti ogni volta che cambi l'oggetto originale cambierai il tuo ricordo.
È possibile eseguire questa operazione utilizzando un serializzatore come protobuf-net o json.net poiché non richiedono di contrassegnare gli oggetti con attributo serializzabile come fa il normale meccanismo di serializzazione .net.
CodeProject hanno pochi articoli su implementazioni Memento generici, ma tendono a saltare la parte deepcopy:
Non sono a conoscenza di alcun modo già integrato per supportare il modello Memento
. Vedo un paio di implementazioni usando .NET Mock frameworks, dove in pratica viene creato un clone dell'oggetto e può essere campo con un dato, ma lo considero un po 'sovraccarico.
L'uso Memento
patter su Annulla/Ripristina di solito, probabilmente anche tu. In questo caso, è meglio avere il minor numero possibile di dati sullo stack Undo/Redo, quindi l'undoable object
personalizzato è qualcosa che sarebbe I.
Spero che questo aiuti.
C'è una cosa che renderà questo schema leggermente più veloce da scrivere in C# e cioè che tutti i campi di stato possono essere dichiarati come public readonly
in modo da non aver bisogno di proprietà o metodi 'get' per accedervi.
Questa è una conversione diretta con public readonly
inclusa.
class Originator
{
private string state;
// The class could also contain additional data that is not part of the
// state saved in the memento.
public void Set(string state)
{
Console.WriteLine("Originator: Setting state to " + state);
this.state = state;
}
public Memento SaveToMemento()
{
Console.WriteLine("Originator: Saving to Memento.");
return new Memento(state);
}
public void RestoreFromMemento(Memento memento)
{
state = memento.SavedState;
Console.WriteLine("Originator: State after restoring from Memento: " + state);
}
public class Memento
{
public readonly string SavedState;
public Memento(string stateToSave)
{
SavedState = stateToSave;
}
}
}
class Caretaker
{
static void Main(string[] args)
{
List<Originator.Memento> savedStates = new List<Originator.Memento>();
Originator originator = new Originator();
originator.Set("State1");
originator.Set("State2");
savedStates.Add(originator.SaveToMemento());
originator.Set("State3");
// We can request multiple mementos, and choose which one to roll back to.
savedStates.Add(originator.SaveToMemento());
originator.Set("State4");
originator.RestoreFromMemento(savedStates[1]);
}
}
Sei sicuro costruttore privato corretto per la classe Memento? è accessibile da Originator? –
Hai ragione! Non ho compilato questo o qualcosa di geez. Ora è stato risolto grazie. –
uno utilizzando Generics ho trovato here:
#region Originator
public class Originator<T>
{
#region Properties
public T State { get; set; }
#endregion
#region Methods
/// <summary>
/// Creates a new memento to hold the current
/// state
/// </summary>
/// <returns>The created memento</returns>
public Memento<T> SaveMemento()
{
return (new Memento<T>(State));
}
/// <summary>
/// Restores the state which is saved in the given memento
/// </summary>
/// <param name="memento">The given memento</param>
public void RestoreMemento(Memento<T> memento)
{
State = memento.State;
}
#endregion
}
#endregion
#region Memento
public class Memento<T>
{
#region Properties
public T State { get; private set; }
#endregion
#region Ctor
/// <summary>
/// Construct a new memento object with the
/// given state
/// </summary>
/// <param name="state">The given state</param>
public Memento(T state)
{
State = state;
}
#endregion
}
#endregion
#region Caretaker
public class Caretaker<T>
{
#region Properties
public Memento<T> Memento { get; set; }
#endregion
}
#endregion
#region Originator
public class Originator<T>
{
#region Properties
public T State { get; set; }
#endregion
#region Methods
/// <summary>
/// Creates a new memento to hold the current
/// state
/// </summary>
/// <returns>The created memento</returns>
public Memento<T> SaveMemento()
{
return (new Memento<T>(State));
}
/// <summary>
/// Restores the state which is saved in the given memento
/// </summary>
/// <param name="memento">The given memento</param>
public void RestoreMemento(Memento<T> memento)
{
State = memento.State;
}
#endregion
}
#endregion
#region Memento
public class Memento<T>
{
#region Properties
public T State { get; private set; }
#endregion
#region Ctor
/// <summary>
/// Construct a new memento object with the
/// given state
/// </summary>
/// <param name="state">The given state</param>
public Memento(T state)
{
State = state;
}
#endregion
}
#endregion
#region Caretaker
public class Caretaker<T>
{
#region Properties
public Memento<T> Memento { get; set; }
#endregion
}
#endregion
si usa così:
Originator<string> org = new Originator<string>();
org.State = "Old State";
// Store internal state in the caretaker object
Caretaker<string> caretaker = new Caretaker<string>();
caretaker.Memento = org.SaveMemento();
Console.WriteLine("This is the old state: {0}", org.State);
org.State = "New state";
Console.WriteLine("This is the new state: {0}", org.State);
// Restore saved state from the caretaker
org.RestoreMemento(caretaker.Memento);
Console.WriteLine("Old state was restored: {0}", org.State);
// Wait for user
Console.Read();
Come @Simon Skov Boisen menzioni questo funziona solo per i dati immutabili e richiede un deep copy.
Vedere la mia risposta, è necessario prendere in considerazione deepcopying quando si tratta di tipi di riferimento con proprietà setter. –
- 1. Memento in Javascript
- 2. Android - Il pattern ViewHolder è implementato automaticamente in CursorAdapter?
- 3. C++ implementato in chiaro C
- 4. Come è implementato il flash Perlin-noise?
- 5. Come implementare il pattern Observer in C++
- 6. Come è implementato il fractions.limit_denominator di python?
- 7. Come è dynamic_cast implementato
- 8. Come è implementato __RTC_CheckEsp?
- 9. Come std :: unordered_map è implementato
- 10. Come viene implementato l'operatore sizeof in C++?
- 11. Ordinamento Radix implementato in C++
- 12. Come è implementato std :: has_virtual_destructor?
- 13. Perché gmtime è implementato in questo modo?
- 14. Come withFile è implementato in Haskell
- 15. come viene implementato il sarcmark?
- 16. È smtplib pure python o implementato in C?
- 17. come viene implementato il multi_index
- 18. Il modello ViewHolder è stato implementato correttamente in CursorAdapter personalizzato?
- 19. Schema di osservatore implementato in C# con i delegati?
- 20. C#: Come dovrebbe essere implementato ToString()?
- 21. Modello MVC C++ - Come deve essere implementato?
- 22. Pattern MVC 4 Autofac e Repository generico
- 23. perché sizeof ('a') è 4 in C?
- 24. Il carattere `A` non è implementato per il tipo` A`
- 25. Come viene implementato "const"?
- 26. Tipo di inferenza implementato in C++
- 27. C# Singleton Pattern e MEF
- 28. In C++ come viene generalmente implementato l'overloading delle funzioni?
- 29. Il pattern Visitor è il modo più veloce per differenziare i tipi di parametri in C++?
- 30. Perché JML non è implementato come annotazioni in Java?
È possibile aggiungere ulteriori informazioni sulla parte di copia profonda? Un link ad un esempio di questa parte dell'implementazione o qualcosa del genere. Ottima risposta quindi grazie ... – MoonKnight
Appena visto il link sottostante. Grazie. – MoonKnight