У меня есть композиция предметов с обременительным дизайном.Классы 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; }
};
Обратите внимание, что std::string _name
в Y
является общедоступным.
Что я хочудля этого нужно получить доступ к Y::_name
через экземпляр X
, записать для него новые значения и иметь возможность легко отменить операцию записи в других частях программы.
Моя попыткаследующим образом: я использую объект 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;
}
};
Если я хочу отменить операцию записи, мне нужно только вызвать метод undoToOldName()
в Undo
object.
Пример:
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.
В качестве ограничения,Я не могу изменить дизайн композиции.
Не могли бы вы предложить альтернативный дизайн?ГНС за это?
Спасибо.