Command Pattern & parameter design
开发者_运维问答My understanding of the Command Pattern is that you simply have 1 virtual method 'execute()', and all dependencies that an implementation might have are put in the constructor or through setter injection in the implementation (like discussed here).
However, in the WPF implementation of the pattern, I noticed they are passing a generic argument to the execute() function (explained here).
This seems like a pollution of the interface to me, what would have been the motivation to add a generic parameter to the execute() function?
The canonical command pattern is usually illustrated with nice self-contained commands. In that any information needed by the command is stashed away within the Command object instance (typically via a parameterized constructor).
However in some cases, the parameters needed for Execute may not be available at command-creation time (are known only at runtime). e.g. Imagine a SignOutCommand( username )
. The username is determined when the user clicks on the SignOut button after signing in first.
So username is passed in as a generic parameter to Command.Execute()
; Each command is free to define its input and cast accordingly e.g. an arbitrary command can require 5 parameters as an object[].
It's for databinding. When you bind the command to every object in a list, for example, the current instance is sent to the execute method so that you don't have to keep track of the current instance yourself.
That said, I don't think that the WPF command notion is an implementation of the command pattern, they just share terminology.
The reason behind that parameter is the isolation between the creator of the command - who know what command needs to be executed, and the caller - who knows when a command need to be executed.
In certain commands some of the information that needed for the execution is not available to the creator. The caller the fills in the blank by passing a parameter to execute. An example: The creator creates a command that filters a list of records according to some criteria. The list is not available at the creation site, as there are many kinds of lists in the application.
The caller will specify which list needs to be filtered by passing at as a parameter.
We use a bit changed command pattern, so that in addition to Execute method we have two properties Request and Response and we parametrize them using polymorphism.
What's wrong with:
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.
}
}
Now if you have a controller that collects parameters you can pass those through to your commands.
精彩评论