Command模式或Strategy模式更适合客户端 - 服务器调用吗?

时间:2014-06-29 16:00:59

标签: c# design-patterns strategy-pattern command-pattern

我需要在求职面试中创建一个客户端 - 服务器程序,客户端发送命令并由服务器处理它们。

服务器需要能够轻松更改,这意味着以后可能会有更多的命令类型。

所以我使用Strategy实现它,这意味着类处理命令看起来类似于:

public class ServerProcessor
{
    Dictionary<string, Action<string>> commandsType;

    public ServerProcessor()
    {
        commandsType = new Dictionary<string, Action<string>>();
    }

    public void RegisterCommand(string commandName, Action<string> command)
    {
        commandsType.Add(commandName, command);
    }

    public void Process(string commandName, string vars)
    {
        if (commandsType.ContainsKey(commandName))
        {
            commandsType[commandName].Invoke(vars);
        }
    }
}

在我这样做之后,面试官说我需要使用Command模式来实现它,但没有说明原因。

命令模式将是这样的:

public interface ICommand
{
    void Execute(string vars);
    string GetName();
}

public class ServerProcessor2
{
    List<ICommand> commandsType;

    public ServerProcessor2()
    {
        commandsType = new List<ICommand>();
    }

    public void RegisterCommand(ICommand commandName)
    {
        commandsType.Add(commandName);
    }

    public void Process(string commandName, string vars)
    {
        foreach (ICommand item in commandsType)
        {
            string name = item.GetName();

            if (name.Equals(commandName))
            {
                item.Execute(vars);
            } 
        }
    }
}

在这种情况下,Command模式更好,还是仅仅是面试官的观点?

3 个答案:

答案 0 :(得分:7)

你的两个例子非常相似。他们都使用策略模式,而不是Command。

策略封装了一个进程,该进程具有给定类型的输入和另一种给定类型的输出。通常战略的选择取决于输入。

Command模式将系统上的操作表示为易于构造,传输和持久化的对象,因此您可以将它们附加到UI元素,对它们进行排队,记录它们,将它们用作撤消的基础等。

您的示例都使用带有命令名称的字符串和带参数的另一个字符串。 Command模式将为每个命令使用不同的类(具有公共超类),并将参数包括为对象的属性。您的示例都使用策略来执行每个命令;在第一个例子中,你的策略是动作,在你的第二个例子中,策略是(有点误导性)ICommands。您的示例实际上只是在命名方面有所不同,并且将其策略存储在字典中而另一个存储在列表中。

现在实际回答你的问题:问题描述中没有任何内容需要使用任何一种模式。命令是客户端 - 服务器接口的一个很好的模式,因为它支持我上面提到的东西,而Strategy是执行命令的一个很好的模式,所以使用它们将是一个不错的选择。然而,两者都不是必需的,所以我们可以告诉Command只是你的面试官的选择(可能是因为他们想知道你是否知道它)。

答案 1 :(得分:2)

在这种情况下使用命令模式的一个好处是可以启用&#34;撤消&#34;一些行动。如果您的ICommand接口实现为:

public interface ICommand
{
    void Execute(string vars);
    void Undo();
    string GetName();
}

当您创建此接口的conrete实现时,为每种类型的命令添加撤消逻辑很容易。例如。如果该命令向文档添加了一些文本,则撤消操作将删除该文本。命令的上下文保存在命令对象中。

服务器可以在执行后将具体的命令对象添加到堆栈中。如果需要撤消操作,则调用代码的简单问题类似于:

executedCommandsStack.pop().undo();

答案 2 :(得分:1)

Command processor pattern面向服务器处理长时间运行的命令。这绝对是命令,而不是战略,因为它是GoF Command的变体。

采访面向Android吗?