Popularny odtwarzacz plików mp3, Winamp oferuje szereg funkcjonalności. Jedną z nich jest losowe wybieranie kolejnych odtwarzanych utworów. Po odsłuchaniu kilku wybranych w ten sposób piosenek, możemy wrócić do pierwszego utwory przechodząc po drodze wszystkie, które do tej pory słuchaliśmy. Następnie można również przejść przez kolejne słuchane utwory aż do ostatniego tak, by potem wylosować kolejny.
Zastosowanie:
Wzorzec Memento jest przydatny w momencie, gdy chcemy w naszej aplikacji zaimplementować funkcjonalność przechodzenia pomiędzy stanami pewnego obiektu, np. cofanie ostatnich zmian. Zatem należy go zastosować w przypadku, gdy potrzebujemy w jakiś sposób śledzić stan naszego obiektu i dokonywać zmian tego stanu.
Zasada działania:
Wprowadza się dwa obiekty : autora (originator), który zmienia swój stan podczas działania programu, oraz dozorcę (caretaker), czyli obiekt który wykonuje operacje na autorze, mające na celu zmianę stanu oraz pobieranie obecnego stanu. Dodatkowo korzysta się z obiektu Memento, który przechowuje stan autora Autor tworzy mementa, natomiast dozorca utrzymuje je, nie ingerując w ich zawartość. To dozorca żąda obiektów memento od autora i gdy zachodzi taka potrzeba oddaje je autorowi. Same mementa powinny być obiektami przechowującymi jedynie stan - bez zachowania, natomiast stan powinien być interpretowany jedynie przez autora. Przeważnie mementa przechowuje się na stosie, pobierając kolejne stany przy kolejnych żądaniach cofania stanu. Można także wprowadzać operację przywracania stanu, co wiąże się z wprowadzeniem drugiego stosu. W przypadku niektórych obiektów można zamiast stanu przechowywać jedynie wykonane operacje i przy próbie przywracania stanu stosować operacje odwrotne, ale nie w każdym przypadku jest to możliwe.
Przykład implementacyjny:
public interface IMemento { object State { get; set; } } public class CalculatorState : IMemento { private object _state; public object State { get { return _state; } set { _state = value; } } } public class SimpleCalculator { public int Value { get; set; } public IMemento GetState() { return new CalculatorState() {State = Value}; } public void RestoreState(IMemento memento) { Value = int.Parse(memento.State.ToString()); } } public class CalculatorCaretaker { private readonly Stack<IMemento> _states = new Stack<IMemento>(); public void StoreState(IMemento item) { _states.Push(item); } public void UndoFunctionality(SimpleCalculator calc) { if(_states.Count > 1) { _states.Pop(); calc.RestoreState(_states.Peek()); } } }
class Program { static void Main(string[] args) { Console.WriteLine("Press number to add, press u to undo"); CalculatorCaretaker caretaker = new CalculatorCaretaker(); SimpleCalculator calculator = new SimpleCalculator(); while(true) { var n = Console.ReadLine(); if(n.Contains('u')) { caretaker.UndoFunctionality(calculator); } else { int nb; bool b = int.TryParse(n, out nb); if(b) { calculator.Value += nb; caretaker.StoreState(calculator.GetState()); } else { break; } } Console.WriteLine(String.Format("The value is : {0} ", calculator.Value)); } } }
Brak komentarzy:
Prześlij komentarz