【问题标题】:What design pattern fits the bill in this scenario?在这种情况下,哪种设计模式符合要求?
【发布时间】:2009-12-06 14:09:53
【问题描述】:

我正在编写一个应用程序来通过 HTTP 网关接收 SMS 消息。我将处理的主要参数是发件人的电话号码和消息本身。但是,根据消息中的关键字,我需要执行不同的逻辑/返回不同的响应。一开始,我使用了一个简单的 if/else,它变成了一个 switch 语句,现在我想把它清理一下。

我认为想要的是某种命令模式的实现,但我不确定。我可以将每个操作实现为命令对象并将它们全部注册到命令处理器,但是我必须实现类似 CanExecute(...) 函数来确定要执行的适当命令。执行命令的条件可能取决于关键字或特定消息内容等多种因素。

我的想法如下:

public interface ISmsCommand 
{
    bool CanExecute(string sender, string message);
    string Execute(string sender, string message);
}

public class SmsHelpCommand : ISmsCommand 
{
    public bool CanExecute(string sender, string message)
    {
        return (message.ToLower().StartsWith("help"));
    }

    public string Execute(string sender, string message) 
    {
        return "For more info, visit...";
    }
}

public class SmsHttpHandler : IHttpHandler
{
    List<ISmsCommand> _commands = new List<ISmsCommand>();

    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        var sender = context.Request.Form[...];
        var message = context.Request.Form["Message"];

        foreach (var command in _commands) 
        {
            if (command.CanExecute(sender, message))
            {
                var response = command.Execute(sender, message);
                SendTextMessage(sender, response);
                break;
            }
        }
    }
}

不过,这段代码在我看来有些可疑。我想我不喜欢将参数同时发送给 CanExecute 函数和 Execute 函数,但我不确定。有什么想法吗?

【问题讨论】:

  • 对各种关键字的响应会是动态/插件吗?这可能会影响执行此操作的方式。
  • 并非如此。命令处理器是相当静态的——我只是想要一种更好的方法来将逻辑从命令接收器/处理程序中抽象出来。

标签: c# design-patterns


【解决方案1】:

我会继续使用命令模式,但请记住,模式只是指导方针(尽管我想这是不言而喻的)。

虽然通常在命令模式中,你会为它提供一些东西来执行它的命令。想想 SqlCommand 对象是如何工作的,你给它一个 SqlConnection 并告诉它执行。命令对象使用 SqlConnection 来执行所需的操作。您将脚放在油门踏板上,它会移动所有连杆,以使汽车行驶得更快。你不要踩油门,然后自己打开油门。

我的建议是,您可以在命令的构造函数中为命令提供SendTextMessage 函数或允许该功能的对象(想想SqlConnection)。或者只是使用Execute 方法以及sendermessage 来提供它。这使您能够只允许命令完成它的工作。同时允许您通过您提供的SendTextMessage 功能限制其执行此操作的能力。如果它可以,它会这样做,如果它不能,因为它不应该给出消息,它不会发送消息。

【讨论】:

    【解决方案2】:

    消息的解析应该在传递给命令之前提前完成。至少足以确定哪个命令适用。换句话说,命令对象不应该负责确定消息是否代表该命令。命令的状态方法应该只确定特定命令是否适用于给定状态。您不必询问每个命令是否需要该消息。

    我会有 GetBalanceCommand、TransferMoneyCommand 等命令。然后有一个简单的字符串标记器解析消息并确定要实例化哪个命令对象并将标记化的字符串传递给命令的 CanExecute/Execute 方法。

    【讨论】:

    • 这会让我回到现在的位置.. 有点长的 if/else 或 switch 语句来解析命令...
    • 我应该详细说明,确定需要执行哪个命令的逻辑并不像每个关键字 1 个命令那么简单。如果是,我只需使用字典查找来确定要执行的命令。
    【解决方案3】:

    看看责任链模式。 http://www.dofactory.com/patterns/PatternChain.aspx。或者您可以将您的 Execute 方法重命名为 TryExecute 并返回一个布尔值。

    【讨论】:

      【解决方案4】:

      【讨论】:

        猜你喜欢
        • 2023-03-10
        • 2012-10-29
        • 1970-01-01
        • 1970-01-01
        • 2016-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多