Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memento模式是如何在C#4中实现的?_C#_Design Patterns_Memento - Fatal编程技术网

Memento模式是如何在C#4中实现的?

Memento模式是如何在C#4中实现的?,c#,design-patterns,memento,C#,Design Patterns,Memento,这个问题本身似乎很直截了当。我正在考虑实现与wikipedia示例相同的功能,但在此之前,是否有C语言的任何功能使其更易于实现或使用?我不知道有任何内置方式支持Memento模式。 我看到了一些使用的实现,在实践中,对象的克隆被创建并且可以用数据字段,但是我认为它有点开销。p> 使用Mementopatteron Undo/Redo通常,可能你也会这样。在这种情况下,最好在撤消/重做堆栈上拥有尽可能少的数据,因此我会选择自定义的可撤消对象 希望这能有所帮助。有一件事可以让这种模式在C#中编写的速

这个问题本身似乎很直截了当。我正在考虑实现与wikipedia示例相同的功能,但在此之前,是否有C语言的任何功能使其更易于实现或使用?

我不知道有任何内置方式支持
Memento
模式。 我看到了一些使用的实现,在实践中,对象的克隆被创建并且可以用数据字段,但是我认为它有点开销。p> 使用
Memento
patteron Undo/Redo通常,可能你也会这样。在这种情况下,最好在撤消/重做堆栈上拥有尽可能少的数据,因此我会选择自定义的
可撤消对象


希望这能有所帮助。

有一件事可以让这种模式在C#中编写的速度稍微快一点,那就是任何状态字段都可以声明为
公共只读
,因此您不需要属性或“get”方法来访问它们

这里是一个包含
public readonly
的直接转换

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]);   
    }
}
类发起人
{
私有字符串状态;
//该类还可以包含不属于该类的其他数据
//国家保存在纪念品中。
公共无效集(字符串状态)
{
Console.WriteLine(“发起者:将状态设置为“+状态”);
this.state=状态;
}
公共纪念品
{
Console.WriteLine(“发起者:保存到Memento”);
归还新的纪念品(州);
}
公共无效恢复通知(Memento Memento)
{
state=memento.SavedState;
Console.WriteLine(“发起者:从Memento还原后的状态:“+状态”);
}
公共类纪念品
{
公共只读字符串SavedState;
公共纪念品(字符串状态保存)
{
SavedState=stateToSave;
}
}
}
班级管理员
{
静态void Main(字符串[]参数)
{
List savedStates=新列表();
发起人发起人=新发起人();
发起人。集合(“状态1”);
发起人。集合(“状态2”);
savedStates.Add(originator.SaveToMemento());
发起人。集合(“State3”);
//我们可以请求多个纪念品,并选择要回滚到的纪念品。
savedStates.Add(originator.SaveToMemento());
发起人。集合(“State4”);
发起人。恢复通知(保存日期[1]);
}
}

我发现了一个使用泛型的:

#地区发起人
公共类发起者
{
#区域属性
公共T状态{get;set;}
#端区
#区域方法
/// 
///创建一个新的纪念品来保存当前的
///陈述
/// 
///创造的纪念品
公共纪念品SaveMemento()
{
归还(新纪念品(州));
}
/// 
///恢复保存在给定memento中的状态
/// 
///赠予的纪念品
公共空间恢复(纪念)
{
状态=memento.State;
}
#端区
}
#端区
#地区纪念品
公共类纪念品
{
#区域属性
公共T状态{get;私有集;}
#端区
#区域导体
/// 
///使用
///给定状态
/// 
///给定状态
公共纪念品(T州)
{
状态=状态;
}
#端区
}
#端区
#地区管理员
公务舱管理员
{
#区域属性
公共纪念品{get;set;}
#端区
}
#端区
#地区发起人
公共类发起者
{
#区域属性
公共T状态{get;set;}
#端区
#区域方法
/// 
///创建一个新的纪念品来保存当前的
///陈述
/// 
///创造的纪念品
公共纪念品SaveMemento()
{
归还(新纪念品(州));
}
/// 
///恢复保存在给定memento中的状态
/// 
///赠予的纪念品
公共空间恢复(纪念)
{
状态=memento.State;
}
#端区
}
#端区
#地区纪念品
公共类纪念品
{
#区域属性
公共T状态{get;私有集;}
#端区
#区域导体
/// 
///使用
///给定状态
/// 
///给定状态
公共纪念品(T州)
{
状态=状态;
}
#端区
}
#端区
#地区管理员
公务舱管理员
{
#区域属性
公共纪念品{get;set;}
#端区
}
#端区
这样使用:

   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();
发起人组织=新发起人();
org.State=“旧州”;
//在看守对象中存储内部状态
看守人=新看守人();
caretaker.Memento=org.SaveMemento();
WriteLine(“这是旧状态:{0}”,org.state);
org.State=“新状态”;
WriteLine(“这是新状态:{0}”,org.state);
//从管理员恢复保存的状态
org.RestoreMento(看守人,纪念品);
WriteLine(“旧状态已还原:{0}”,org.state);
//等待用户
Console.Read();

正如@Simon Skov Boisen提到的,这只适用于不可变的数据,并且需要一个特殊的属性。

一个明显的特性是泛型,实现泛型memento将允许您将其用于任何您想要的对象

您将看到的许多示例将使用字符串(包括当前对此问题的答复中的所有字符串)作为状态,这是一个问题,因为它是.NET中为数不多的不可变类型之一

当处理可变对象(像任何具有setter属性的引用类型)时,您必须记住,在保存memento时,您需要创建对象的deepcopy。否则,无论何时更改原始对象,都会更改纪念品

您可以通过使用类似或的序列化程序来实现这一点,因为它们不需要像正常的.net序列化机制那样使用可序列化属性标记对象

Codeproject几乎没有关于ge的文章
   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();