Bản thân số Memento Pattern có vẻ khá thẳng về phía trước. Tôi đang xem xét việc thực hiện giống như ví dụ wikipedia, nhưng trước khi tôi làm là có bất kỳ tính năng ngôn ngữ của C# mà làm cho nó dễ dàng hơn để thực hiện hoặc sử dụng?Mẫu Memento được triển khai như thế nào trong C# 4?
Trả lời
Một tính năng hiển nhiên sẽ là generics, việc triển khai một bộ lưu trữ chung sẽ cho phép bạn sử dụng nó cho bất kỳ đối tượng nào bạn muốn.
Nhiều ví dụ mà bạn sẽ thấy sẽ sử dụng một chuỗi (bao gồm tất cả những câu trả lời cho câu hỏi này) vì đây là một vấn đề vì đây là một trong số ít loại .NET là không thay đổi.
Khi xử lý các đối tượng có thể thay đổi (như bất kỳ loại tham chiếu nào với thuộc tính setter), bạn phải nhớ rằng khi lưu lưu trữ, bạn cần tạo bản in sâu của đối tượng. Nếu không, bất cứ khi nào bạn thay đổi đối tượng ban đầu của bạn, bạn sẽ thay đổi vật lưu niệm của bạn.
Bạn có thể thực hiện việc này bằng cách sử dụng trình nối tiếp như protobuf-net hoặc json.net vì chúng không yêu cầu bạn đánh dấu đối tượng bằng thuộc tính tuần tự như cơ chế tuần tự .net bình thường.
CodeProject có vài bài viết về hiện thực vật lưu niệm chung chung, nhưng họ có xu hướng bỏ qua phần deepcopy:
Tôi không biết bất kỳ cách nào được tích hợp sẵn để hỗ trợ mẫu Memento
. Tôi thấy một vài triển khai bằng cách sử dụng .NET Mock frameworks, trong đó trong thực tế một bản sao của đối tượng được tạo ra và có thể là trường với dữ liệu, nhưng tôi xem xét nó là loại phí.
Sử dụng Memento
patter khi Hoàn tác/Làm lại thường, có thể bạn cũng vậy. Trong trường hợp này, tốt hơn nên có ít dữ liệu hơn trên Hoàn tác/Làm lại ngăn xếp càng tốt, do đó, tùy chỉnh undoable object
là một cái gì đó mà Tôi sẽ sử dụng.
Hy vọng điều này sẽ hữu ích.
Có một điều sẽ làm cho mẫu này nhanh hơn để viết trong C# và đó là bất kỳ trường trạng thái nào có thể được khai báo là public readonly
vì vậy bạn không cần các thuộc tính hoặc phương thức 'get' để truy cập chúng.
Đây là chuyển đổi thẳng với public readonly
bao gồm.
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]);
}
}
Bạn có chắc chắn xây dựng tư nhân chính xác cho lớp Memento? là nó có thể truy cập từ Originator? –
Bạn đã đúng! Tôi đã không biên dịch điều này hoặc một cái gì đó geez. Bây giờ cố định của nó nhờ. –
một sử dụng Generics tôi đã tìm thấy 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
Được sử dụng như thế này:
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();
Như @Simon Skov Boisen đề cập đến điều này sẽ chỉ làm việc cho dữ liệu không thay đổi và đòi hỏi một deep copy.
Xem câu trả lời của tôi, bạn phải xem xét sâu hơn khi xử lý các loại tham chiếu với các thuộc tính setter. –
- 1. Làm thế nào là java.io.Serializable mẫu Memento?
- 2. C# Generics được triển khai như thế nào?
- 3. OpenID được triển khai như thế nào?
- 4. HttpSession được triển khai như thế nào?
- 5. Máy tính Google được triển khai như thế nào?
- 6. Chuỗi string.find được triển khai như thế nào trong CPython?
- 7. Các mảng được triển khai trong Perl như thế nào?
- 8. Các mảng được triển khai trong java như thế nào?
- 9. Các khối try/catch được triển khai như thế nào?
- 10. IO không chặn được triển khai như thế nào?
- 11. Cách đối sánh mẫu trong Scala được triển khai ở cấp độ bytecode như thế nào?
- 12. LLVM isa <> được triển khai như thế nào?
- 13. GMail triển khai Comet như thế nào?
- 14. Atan2 được triển khai bằng .NET như thế nào?
- 15. Thuộc tính phụ thuộc được triển khai như thế nào?
- 16. Các tham chiếu yếu được triển khai như thế nào?
- 17. Arrays.sort (Object [] a) - được triển khai như thế nào?
- 18. Bản đồ băm JavaScript được triển khai như thế nào?
- 19. "Gọi lại" trong C là gì và chúng được triển khai như thế nào?
- 20. Hồ sơ luồng sẽ được triển khai như thế nào trong C?
- 21. GetHashCode() được triển khai cho Int32 như thế nào?
- 22. Facebook Chat Heads được triển khai như thế nào?
- 23. Phạm vi Lexical được triển khai như thế nào?
- 24. Các mutex được triển khai như thế nào?
- 25. Triển khai mẫu Phương thức mẫu trong C#
- 26. Sự đa thừa kế của C++ được triển khai như thế nào?
- 27. Tùy chọn BarSpacing thực sự được triển khai như thế nào trong Mathematica?
- 28. Làm thế nào để bạn triển khai giao diện IDynamicObject của C# 4?
- 29. Các ứng dụng Java được triển khai như thế nào trong "thế giới thực"?
- 30. Máy phát điện và coroutines được triển khai như thế nào trong CPython?
Bạn có thể thêm bất kỳ thông tin nào khác về phần bản sao sâu không? Một liên kết đến một ví dụ về phần này của việc thực hiện hoặc một cái gì đó. Câu trả lời tuyệt vời để cảm ơn ... – MoonKnight
Chỉ cần nhìn thấy liên kết bên dưới. Cảm ơn. – MoonKnight