There is one problem about this pattern that troubles me.
In a situation when we have to save a state into a file, is it class Memento that should be responsible for handling this process? (for example, providing SaveToFile and RestoreFromFile functions)
3
Short answer: No.
Long answer:
Think back to the Single Responsibility Principle. An object (or method, or module) should only have one reason to exist. That reason may be large or small, but it is cohesive. A memento exists to manage temporal state. In other words, track state as it changes, to allow moving backward and forward through those states. The goal of the memento pattern is essentially to enable chaining undo/redo (ctrl+Z/ctrl+Y) operations.
Those mementos may be serializable and the originator may also be serializable. Those serialized forms may be suitable for saving to disk, memory buffer, printing on paper, whatever you want: but the memento itself is not concerned with saving anything to disk. That is not its responsibility.
While an object may know how to serialize and deserialize itself1, generally the action of actually saving or loading to/from disk or anything else is the responsibility of another object. That is the idea behind “serialization”: it is a very broad interface between any object that has a potential need to copy itself to another location, and objects responsible for communicating with those locations.
This is typically done with streams. Serialization really just means “convert this object into a string of bytes or characters” which a stream can then consume. The stream could be a file stream for saving/loading to/from a file on disk, the network, etc. It could be backed by a socket, HTTP, a web service, anything. The memento does not need to know what a “disk” is or what a “file” is.
1 While it may be appropriate for a simple object or a single object to manage its own serialization, a complex object or a module with a lot of objects (e.g. a group of DAOs) may be better served with objects that manage serialization for them. There is overhead associated with this, and it only makes sense to spend the time and effort when it makes the system design clearer.