制作外部数据结构更新器的有效方法UI
The efficient way to make external data structure updater UI
我有一个class包含很多属性。其中一个需要一个特殊的 UI 来编辑。
用户可以在 UI 中按编辑此 属性 然后他进行更改并按确定或取消
例如
class A{
private List<Employee> employees;
public void EditMyEmployees(){
EmployeeEditorForm editor = new EmployeeEditor(employees);
if(editor.ShowDialog() == DialogResult.OK){
employees = editor.GetEditedEmployeesList();
}
}
}
之前代码中编辑器有对员工列表的引用的副本的问题
当编辑器在列表中进行任何编辑时,它会反映在原始对象中。
因此,按 OK 或 Cancel 将具有相同的效果(对象已经更新)并且不需要步骤
employees = editor.GetEditedEmployeesList();
我知道在将 employees 数组发送给编辑器之前对其进行深度复制可以解决问题,但我仍然认为这不是有效的方法
我正在寻找一种可以更好地实现这一点的设计模式。
你不一定需要深拷贝整个collection。您只需要跟踪更改的元素。在您的 EmployeeEditor
中,使用三个列表(List<Employee>
来跟踪:
- 已添加员工
- 已删除的员工
- 更换了员工
取消后,您需要删除 "added" 项,添加回 "removed" 项,并将更改的项目替换为其原始状态。
请注意,更改后的员工列表需要保留 object 原始状态的副本。如果 Employee
class 有某种独特的 ID,您可以匹配该 ID 的大小写。否则,"changed" 列表需要是 List<Tuple<Employee, Employee>>
以便您可以存储匹配项。
另请注意,当员工列表发生变化时,您还需要对这三个列表进行必要的更改。例如,如果添加了一个新员工然后将其删除,您还需要从 "added" 列表中删除该记录。或者有可能更换员工然后将其删除,在这种情况下,您还需要从 "changed" 列表中删除。
说了这么多,如果我是你,我会根据预期的用例和真实的性能问题(而不是预期的性能问题)做出决定。很可能简单地深度复制您的 collection 是最简单且最不容易出错的方法。
此处涉及两种更改:(1) 更改列表(添加/删除)和 (2) 更改列表的单个元素(在本例中为员工)。
现在,部分问题来自OK/Cancel的语义。如果您将这两个按钮的范围限制为第二种更改(即,对列表元素的更改),您将能够通过此特定操作的确认对话框处理删除("Remove such and such"?) .对于 Addition,您不需要任何特殊的东西,只需向列表中添加一个新元素即可。如果用户改变主意,他们仍然可以使用删除操作。
对于特定元素(第二种)的更改,您可以使用评论中提到的命令模式。更简单地说,您可以为编辑器从 edition 下的元素显示的所有字段初始化临时变量。当用户修改某些值时,您的编辑器将更新相应的临时值。如果用户按下取消,您将忘记这些更改(或从元素中重新初始化它们)。如果用户按下 Apply(是的,您还应该包括 Apply 按钮),您现在会将每个临时值写入相应元素的属性。如果用户点击确定,您将应用并关闭。
我有一个class包含很多属性。其中一个需要一个特殊的 UI 来编辑。 用户可以在 UI 中按编辑此 属性 然后他进行更改并按确定或取消
例如
class A{
private List<Employee> employees;
public void EditMyEmployees(){
EmployeeEditorForm editor = new EmployeeEditor(employees);
if(editor.ShowDialog() == DialogResult.OK){
employees = editor.GetEditedEmployeesList();
}
}
}
之前代码中编辑器有对员工列表的引用的副本的问题
当编辑器在列表中进行任何编辑时,它会反映在原始对象中。 因此,按 OK 或 Cancel 将具有相同的效果(对象已经更新)并且不需要步骤
employees = editor.GetEditedEmployeesList();
我知道在将 employees 数组发送给编辑器之前对其进行深度复制可以解决问题,但我仍然认为这不是有效的方法
我正在寻找一种可以更好地实现这一点的设计模式。
你不一定需要深拷贝整个collection。您只需要跟踪更改的元素。在您的 EmployeeEditor
中,使用三个列表(List<Employee>
来跟踪:
- 已添加员工
- 已删除的员工
- 更换了员工
取消后,您需要删除 "added" 项,添加回 "removed" 项,并将更改的项目替换为其原始状态。
请注意,更改后的员工列表需要保留 object 原始状态的副本。如果 Employee
class 有某种独特的 ID,您可以匹配该 ID 的大小写。否则,"changed" 列表需要是 List<Tuple<Employee, Employee>>
以便您可以存储匹配项。
另请注意,当员工列表发生变化时,您还需要对这三个列表进行必要的更改。例如,如果添加了一个新员工然后将其删除,您还需要从 "added" 列表中删除该记录。或者有可能更换员工然后将其删除,在这种情况下,您还需要从 "changed" 列表中删除。
说了这么多,如果我是你,我会根据预期的用例和真实的性能问题(而不是预期的性能问题)做出决定。很可能简单地深度复制您的 collection 是最简单且最不容易出错的方法。
此处涉及两种更改:(1) 更改列表(添加/删除)和 (2) 更改列表的单个元素(在本例中为员工)。
现在,部分问题来自OK/Cancel的语义。如果您将这两个按钮的范围限制为第二种更改(即,对列表元素的更改),您将能够通过此特定操作的确认对话框处理删除("Remove such and such"?) .对于 Addition,您不需要任何特殊的东西,只需向列表中添加一个新元素即可。如果用户改变主意,他们仍然可以使用删除操作。
对于特定元素(第二种)的更改,您可以使用评论中提到的命令模式。更简单地说,您可以为编辑器从 edition 下的元素显示的所有字段初始化临时变量。当用户修改某些值时,您的编辑器将更新相应的临时值。如果用户按下取消,您将忘记这些更改(或从元素中重新初始化它们)。如果用户按下 Apply(是的,您还应该包括 Apply 按钮),您现在会将每个临时值写入相应元素的属性。如果用户点击确定,您将应用并关闭。