简体   繁体   English

在这种情况下,哪种设计模式符合要求?

[英]What design pattern fits the bill in this scenario?

I'm writing an application to receive SMS messages via an HTTP gateway. 我正在编写一个通过HTTP网关接收SMS消息的应用程序。 The main parameters I'll be processing are the sender's phone number and the message itself. 我要处理的主要参数是发件人的电话号码和消息本身。 However, depending on the keyword within the message, I'll need to execute different logic / return a different response. 但是,根据消息中的关键字,我将需要执行不同的逻辑/返回不同的响应。 To start with, I used a simple if/else which turned into a switch statement, and now I'm looking to clean it up a bit. 首先,我使用了一个简单的if / else,它变成了switch语句,现在我希望对其进行一些清理。

I think what want is some sort of implementation of the command pattern, but I'm not sure. 我认为所需的是命令模式的某种实现,但是我不确定。 I could implement each operation as a command object and register them all with the command processor, but then I'd have to implement something like a CanExecute(...) function to determine the appropriate command to execute. 我可以将每个操作实现为命令对象,并在命令处理器中全部注册它们,但是随后我必须实现类似CanExecute(...)函数的功能,以确定要执行的适当命令。 The conditions for which a command should be executed may depend on several factors such as the keyword or specific message content. 命令执行的条件可能取决于几个因素,例如关键字或特定的消息内容。

I'm thinking something like the following: 我在想以下内容:

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;
            }
        }
    }
}

Something about this code seems fishy to me, though. 不过,对于我来说,有关此代码的某些内容似乎很糟糕。 I think I don't like having to send the arguments to both the CanExecute function and the Execute function, but I'm not sure. 我认为我不喜欢将参数同时发送到CanExecute函数和Execute函数,但是我不确定。 Any thoughts? 有什么想法吗?

The parsing of the message should be done ahead of time before passing to the command. 消息的解析应该在传递给命令之前提前进行。 At least enough to determine which command is applicable. 至少足以确定哪个命令适用。 In other words, it should not be the responsibility of a command object to determine whether or not a message represents that command. 换句话说,确定消息是否代表该命令不是命令对象的责任。 The command's status method should only determine whether or not a particular command is applicable in a given state. 命令的状态方法应仅确定特定命令在给定状态下是否适用。 You shouldn't have to ask each command if it wants the message. 您不必询问每个命令是否需要消息。

I would have commands like GetBalanceCommand, TransferMoneyCommand, etc. Then have a simple string tokenizer parse the message and determine which command object to instantiate and pass the tokenized string to the command's CanExecute/Execute methods. 我将拥有诸如GetBalanceCommand,TransferMoneyCommand之类的命令,然后让一个简单的字符串令牌生成器解析消息并确定要实例化哪个命令对象,并将令牌化字符串传递给命令的CanExecute / Execute方法。

Have a look at the Chain of Responsibility pattern. 看看责任链模式。 http://www.dofactory.com/patterns/PatternChain.aspx . http://www.dofactory.com/patterns/PatternChain.aspx Or you can rename your Execute method to TryExecute and return a bool. 或者,您可以将Execute方法重命名为TryExecute并返回布尔值。

看一下Factory方法命令和Command模式。

I would continue with the command pattern, but remember that patterns are just guidelines (though I imagine that goes without saying). 我将继续使用命令模式,但请记住,这些模式仅是指导原则(尽管我想当然不用说了)。

Though normally in the command pattern you supply it with something to execute it's command upon. 尽管通常在命令模式下,您会为其提供执行命令的功能。 Think of how the SqlCommand object works, you give it the SqlConnection and just tell it to execute. 考虑一下SqlCommand对象是如何工作的,为它提供SqlConnection并告诉它执行。 The command object uses the SqlConnection to do what is needed. 该命令对象使用SqlConnection来执行所需的操作。 You put your foot on the gas pedal and it moves all the linkages in order to make the car go faster. 您将脚踩在油门踏板上,它会移动所有连杆,以使汽车行驶更快。 You don't push the gas pedal and then open the throttle yourself. 您无需踩油门踏板然后自己打开油门。

What I would suggest is that you either give the command the SendTextMessage function or object that allows for that functionality (think of the SqlConnection) in it's constructor. 我的建议是,您可以在命令的SendTextMessage函数中为命令提供SendTextMessage函数或允许该功能的对象(例如SqlConnection)。 Or just give it with the Execute method along with the sender and the message . 或者只是将Execute方法与sendermessage一起提供给它。 This gives you the ability to just allow the command to do it's job. 这使您能够只允许命令完成任务。 While at the same time allowing you to constrain its ability to do that via the SendTextMessage functionality you provide it. 同时允许您通过提供的SendTextMessage功能来限制其执行此操作的能力。 It will do it if it can and if it cannot, because it's not supposed to given the message, it won't send the message. 如果可以,它将执行此操作,因为它不应该给出消息,因此不会发送消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM