我有一个包含很多属性的类。其中一个需要编辑特殊的UI。 用户可以在UI中按此编辑到该属性,然后他进行更改并按“确定”或“取消”
e.g。
class A{
private List<Employee> employees;
public void EditMyEmployees(){
EmployeeEditorForm editor = new EmployeeEditor(employees);
if(editor.ShowDialog() == DialogResult.OK){
employees = editor.GetEditedEmployeesList();
}
}
}
上一代码中的问题是编辑器具有对员工列表的引用的副本
当编辑器在List中进行任何编辑时,它将反映在原始对象中。 因此,按OK或取消将产生相同的效果(对象已更新),无需执行步骤
employees = editor.GetEditedEmployeesList();
我知道在发送给编辑器之前为employees数组制作深层副本将解决问题,但我认为这不是有效的方法
我正在寻找能够以更好的方式实现这一目标的设计模式。
答案 0 :(得分:1)
您不一定需要深入复制整个集合。您只需要跟踪已更改的元素。在EmployeeEditor
中,使用三个列表(List<Employee>
来跟踪:
取消后,您需要删除&#34;添加&#34;项目,添加&#34;删除&#34;项目,并将更改的项目替换为其原始状态。
请注意,更改后的员工列表需要保留对象原始状态的副本。如果Employee
类具有某种唯一ID,则可以匹配该ID。否则,&#34;改变&#34; list必须是List<Tuple<Employee, Employee>>
,以便您可以存储匹配的项目。
另请注意,当员工列表中发生更改时,您还需要对这三个列表进行必要的更改。例如,如果添加了一个新员工然后将其删除,您还需要从&#34;添加&#34;名单。或者员工可能会被更改然后被删除,在这种情况下,您还需要从&#34;更改&#34;名单。
说完这一切之后,如果我是你,我会根据预期的用例和真正的性能问题(不是预期的性能问题)做出决定。简单地深度复制您的集合很可能是最简单且最不容易出错的方式。
答案 1 :(得分:1)
此处涉及两种更改:(1)更改列表(添加/删除)和(2)更改列表中的各个元素(本例中为员工)。
现在,部分问题来自OK / Cancel的语义。如果您将这两个按钮的范围限制为第二种类型的更改(即更改列表元素),您将能够通过此特定操作的确认对话框处理删除(“删除此类等”? )。对于Addition,您不需要任何特殊内容,只需在列表中添加一个新元素即可。如果用户改变主意,他们仍然可以使用“删除”操作。
对于特定元素(第二类)的更改,您可以使用注释中提到的命令模式。更简单地说,您可以为编辑器显示的所有字段初始化临时变量。当用户修改某些值时,编辑器将更新相应的临时值。如果用户按下取消,您将忘记这些更改(或从元素重新初始化它们)。如果用户按Apply(是的,您还应该包括Apply按钮),现在将每个临时值写入相应元素的属性。如果用户点击OK,您将应用并关闭。