【发布时间】:2020-07-05 22:26:19
【问题描述】:
在互联网上,我遇到了 memento 模式的实现示例 我认为这是完全不正确的。 它们可以用 Java 和 C# 编写。
这里有几个
- Incorrect implementation of Memento pattern 1
- Incorrect implementation of Memento pattern 2
- Incorrect implementation of Memento pattern 3
代码:
public class Originator
{
private string _state; //the private field of originator that shouldn't be exposed!!!!
public Memento CreateMemento()
{
return new Memento(_state);
}
public void SetMemento(Memento memento)
{
_state = memento.GetState();
}
}
public class Memento
{
private string _state;
public Memento(string state)
{
_state = state;
}
public string GetState()
{
return _state; // here caretaker can access to private field of originator!!!
}
}
public class Caretaker
{
public Memento Memento { get; set; }
}
在代码中我留下了应该描述情况的 cmets。
看守类可以通过备忘录读取发起者的私有字段,这违反了备忘录模式的主要原则之一:
不得违反对象的封装性。
所以问题是我是对的吗?
【问题讨论】:
-
int将被复制到Memento构造函数,所以Memento._state和Originator._state是两个不同的,独立的ints(与string相同) -
@vborutenko,不要尝试
object.ReferenceEquals(Memento._state, Originator._state)。此外,更改为Originator._state不会更改Memento._state,反之亦然 -
在引用类型和值类型上看起来有点误解
-
@vborutenko,不,它无权访问
Originator私有字段。它存储前一段时间在该字段中的 值(string/int的副本)。所以,如果Originator以某种方式改变了他的_state,Memento将永远不会知道这一点。同时,如果Momento以某种方式更改他的_state(他自己的那个string/int值的副本) - 这将永远不会对Originators_state做任何事情 -
@vborutenko,好的,现在我知道你有什么困扰了。公开私有字段的值(副本)并不违反封装。以您的示例为例,应该有 "嗨。我是看守人,我知道发起者的私有字段 '_state' 的值等于" + memento.GetState() + " 不久前,现在可能会改变,IDK。”
标签: c# oop design-patterns memento