2010-01-29 62 views
2

我对Command模式的理解是,你只需要一个虚拟方法'execute()',并且实现可能具有的所有依赖项都放在构造函数中,或者通过setter注入实现中讨论了here)。但是,在模式的WPF实现中,我注意到他们正在向execute()函数传递通用参数(解释为here)。命令模式和参数设计

这看起来像是对我的界面的污染,那么为execute()函数添加通用参数的动机是什么?

回答

1

这是数据绑定。例如,当您将命令绑定到列表中的每个对象时,当前实例将被发送到execute方法,以便您不必亲自跟踪当前实例。

这就是说,我不认为WPF命令的概念是命令模式的实现,他们只是分享术语。

1

该参数背后的原因是命令的创作者之间的隔离 - 在呼叫者谁知道要执行命令需要什么, - 谁知道命令需要执行。

在某些命令中,执行所需的某些信息对于创建者不可用。调用者通过传递一个参数来填充空白。示例:创建者创建一个命令,根据某些条件过滤记录列表。该列表在创建站点不可用,因为应用程序中有许多种列表。

调用者将指定哪个列表需要通过作为参数传递来过滤。

+0

在你的例子中,我希望有一个特定的接口用于在列表上工作的命令,它将列表(或列表的接口)作为参数,而不是某种通用参数。 – eli 2010-01-29 10:18:44

+0

@ eli.work:我没有说参数需要通用。我刚才说过,执行所需的数据并不总是在创建命令对象的站点上可用的。 – 2010-01-29 10:55:59

+0

我的问题应该更清楚一点:它是我想知道的泛型参数的动机。我会更新我的问题,并感谢您的回复! – eli 2010-01-29 11:00:13

1

我们使用了一点变化的命令模式,因此除了Execute方法之外,我们还有两个属性Request和Response,并且我们使用多态性对它们进行参数化。

3

典型的命令模式通常用很好的自包含命令来说明。因为该命令所需的任何信息都隐藏在Command对象实例内(通常通过参数化构造函数)。

但是在某些情况下,Execute所需的参数在命令创建时可能不可用(仅在运行时才可知)。例如想象一下SignOutCommand(username)。用户名是在用户首次登录后单击SignOut按钮时确定的。

因此,用户名作为通用参数传递到Command.Execute();每个命令可自由定义其输入并相应地投射一个任意的命令可能需要5个参数作为对象[]。

+0

我明白了,但为什么不定义一个单独的接口,或者创建一个从其他地方获取用户名的命令实现(如IUserNameGetter)? – eli 2010-01-29 10:33:18

+0

@ eli.work这是一种我认为简单与优雅之间的折衷。使用IUserNameGetter,您必须创建此新类型的实例并将其存储在Command对象中。每次执行调用时,命令对象都会再次发送消息以从GUI中检索用户名。比传入输入更加健谈。此外,WPF限制从创建它的线程访问GUI,您可能需要在IUserNameGetter impl中执行线程验证和切换(例如,如果在工作线程上调用Command.Execute)。 – Gishu 2010-01-29 11:03:11

1

出了什么问题:

public class DeleteCommand : BaseCommand 
{ 
    private Dictionary<string, object> parameters; 

    public DeleteCommand(Dictionary<string, object> parameters) 
    { 
    this.parameters = parameters; 
    } 

    public void Execute() 
    { 
    var person = (Person)parameters["Person"]; 
    var salary = System.Convert.ToDouble(parameters["Salary"]); 

    // etc. 
    } 
} 

现在,如果你有一个控制器,它收集的参数可以把它们通过对你的命令。

+1

我在我编写的测试自动化框架中使用了类似的方法,但我将Dictionary传递给Execute方法,以便Action对象可以保持无状态并因此被缓存。 – 2010-11-18 23:27:34