我以前曾经多次遇到过这个问题,而且我从未有过一个我感觉良好的解决方案。
假设我有一个Transaction基类和两个派生类AdjustmentTransaction和IssueTransaction。
我在UI中有一个事务列表,每个事务都是具体类型AdjustmentTransaction或IssueTransaction。
当我选择一个交易,然后点击“编辑”按钮时,我需要决定是否显示一个AdjustmentTransactionEditorForm或一个IssueTransactionEditorForm。
问题是我如何以OO方式执行此操作而无需对所选事务的类型使用switch语句? switch语句有效,但感觉很糟糕。我觉得我应该能够以某种方式利用Transactions和TransactionEditors之间的并行继承层次结构。
我可以在我的交易中拥有一个EditorForm属性,但这是我的UI花生酱和我的模型巧克力的可怕混合。
提前致谢。
答案 0 :(得分:1)
您需要在某个时刻将“EditorForm”映射到事务。你有几个选择:
在C#中,我实现了一个Type - >像这样的表格映射器:
Dictionary <Type,Type> typeMapper = new Dictionary<Type,Type>();
typeMapper.Add(typeof(AdjustTransaction), typeof(AdjustTransactionForm));
// etc, in this example, I'm populating it by hand,
// in real life, I'd use a key/value pair mapping config file,
// and populate it at runtime.
然后,点击编辑时:
Type formToGet;
if (typeMapper.TryGetValue(CurrentTransaction.GetType(), out formToGet))
{
Form newForm = (Form)Activator.CreateInstance(formToGet);
}
答案 1 :(得分:1)
你可能不希望将它绑定到继承树 - 当你稍微改变需求时,这会很好地约束你。
应该在外部文件中的某处指定关系。描述这种关系的东西:
Editing AdujustmentTransaction = AdjustmentTransactionEditorForm
Editing IssueTransaction = IssueTransactionEditorForm
通过一些解析和一些比我在这里使用的更好的语言,这个文件可以变得非常通用和可重用 - 如果需要,你可以重用不同对象的表单,或者改变用于编辑对象的表单没有太多的努力。
(您可能希望名为“Joe”的用户改为使用“JoeIssueTransactionEditorForm”,这可以很容易地用到您的“语言”中)
这实质上是依赖注入 - 您可以使用Spring以更笼统的方式解决问题。
答案 2 :(得分:0)
我是否想念问题?我只是问,因为明显的OO答案是:Polymorph
只需执行Transaction.editWindow()(或者你想调用它),和 使用所需的功能覆盖AdjustmentTransaction和IssueTrasaction中的方法。然后,对element.editWindow()的调用将为您打开正确的对话框。
答案 3 :(得分:0)
字典/配置文件方法的替代方法是
1)为每个交易编辑者定义一个接口。
2)在EXE或UI程序集中,每个表单都使用创建单个事务的程序集注册自身。
3)控制注册的类应该是单例,因此您没有多个表单实例浮动。
3)创建单个事务时,它会从注册对象中提取正确的表单变量,并指定它执行内部变量。
4)当调用Edit方法时,它只使用内部方法的Show方法来启动将导致该transacton编辑器显示的调用链。
这消除了对配置文件和词典的需要。它继续将UI与对象分开。另外,您不需要任何开关声明
缺点是除了表单本身之外,还必须为每个表单编写接口。
如果您有大量不同类型的编辑器(数十种),那么在这种情况下我建议您使用命令模式
你有一个主命令,其中包含Jonathan推荐的dictonary。该命令轮流将使用该dictornary执行许多其他命令之一,该命令使用正确的对象调用正确的表单。表格继续与对象本身分开。表单驻留在Command程序集中。此外,您不必更新EXE以仅添加另一个编辑器Command组件。最后,通过将命令置于Command中,您可以更轻松地实现撤消/重做。 (实现Unexecute和Execute)