【发布时间】:2012-04-03 20:46:37
【问题描述】:
我有一个设计繁琐的对象组合。 X 和 Y 类是此设计的示意图,其中 Y 是 X 的一个组件。
class Y {
public:
std::string _name;
Y(std::string name) : _name(name) {}
};
class X {
Y _y;
public:
X(std::string name) : _y(name) {}
Y getY() { return _y; }
Y* getYPtr() { return &_y; }
};
注意Y 中的std::string _name 是公开的。
我想做的是通过X 的实例访问Y::_name,为其写入新值,并有可能在程序的其他部分轻松撤消写入操作。
我的尝试如下:我使用一个包含三个信息的Undo对象:
- 撤消生效的字符串指针
- 包含旧名称的字符串
- 包含新名称的字符串
.
class Undo {
std::string _oldName;
std::string _newName;
std::string *_internalName;
public:
Undo(std::string *name) : _internalName(name) {}
void setOldName(std::string oldName) {
_oldName = oldName;
}
void setNewName(std::string newName) {
_newName = newName;
}
void undoToOldName() {
*_internalName = _oldName;
}
};
如果我想撤消一个写操作,我只需要在Undo对象上调用undoToOldName()方法。
例子:
X x("firstName");
Y *y = x.getYPtr();
// Prepare the undo object
Undo undo(&(y->_name));
undo.setOldName(y->_name);
undo.setNewName("secondName");
// Set new name
y->_name = "secondName";
// Output: secondName
std::cout << x.getY()._name << std::endl;
// Undo
undo.undoToOldName();
// Output: firstName
std::cout << x.getY()._name << std::endl;
我不喜欢这种设计的一点是需要Y * getter。
作为一个约束,我不能改变构图的设计。
您能否为此推荐替代设计?
谢谢。
【问题讨论】:
-
是否允许使用
X::setY()方法?如果是这样,它将允许删除getYPtr()并实现X::rollbackY()方法。 -
也许让你的 Undo 类成为 Y 的朋友,所以它可以设置
_y._name?如果您希望 Undo 记住要处理哪个 X 或 Y,它可以在构造函数中获取一个引用,并且 - 使用初始化列表 - 记录它以供以后使用。避免指针。坦率地说,虽然这有点乱...... :-( -
@hmjd 感谢您的评论。不,这是不可能的,因为一个
X有许多类似于Y的对象。其中只有一个是有效的,这由枚举确定。一旦我发现要编辑哪个Y,我就不想再通过枚举了。此外,一个Y有许多_ys,并不是所有的_ys 都有资格撤消。我承认设计很丑,但这就是我拥有的图书馆:)。 -
@TonyDelroy 感谢您的建议,但我认为这行不通,因为 Y 中有许多
y_s。在问题中省略了这个细节是我的错。
标签: c++ design-patterns undo