当前位置: 首页 > 知识库问答 >
问题:

使用命令模式通过串行发送和接收命令

公孙慎之
2023-03-14

我正在使用一个桌面应用程序,它应该通过串行接口发送和接收命令,固件由我的同事编程

我们设计了一个协议,其中命令类型由ASCII字母表示,每个命令类型可能包含一个有效载荷(在命令类型之间是任意的,但是对于每种类型是固定的),并且命令被包装在方括号中。例如,我们有以下命令:

  • [S1234]-

所以我有一个接收和解析传入字节的类,每次成功解析命令时,都会引发一个事件,并带有以下暂定签名:

internal event EventHandler<SerialCommand> CommandReceived;

其中< code>SerialCommand有不同的子类型:BatteryCommand、AdcCommand、SerialCommand等。每种命令类型都与其各自的“字符代码”相关联。

我的问题是:客户端代码应该如何使用它?例如,当我收到命令时的当前实现有一个带有硬编码char文字的开关/案例,我发现它非常脆弱和丑陋:

    void CommandReceivedHandler(object sender, SerialCommand command)
    {
        switch (command.Code)
        {
            case 'A':
                int value= Convert.ToInt32(command.Value);
                _frameStreamer.AddFrame(new Frame<int>(new[] { value}));
                break;
            case 'B':
                BatteryLevel= (int)command.Value;
                break;
            case 'D':
                DoSomething((byte)command.Value);
                break;
            case 'S':
                SerialNumber = (int)command.Value;
                break;
        }           
    }

目前,这些“字符代码”分布在一堆类中,如果我需要更改给定的代码,我需要环顾四周以查找每个事件(霰弹枪手术反模式)。

我需要做的是两件事:

  • 仅将字符代码封装在命令中,而不是客户端代码中;
  • 在客户端(CommandReceived 事件使用者)上多态执行操作,最好不使用开关/case 语句。

共有1个答案

司空兴为
2023-03-14

你可以试试这样的方法:

public abstract class BaseCommand
{
    //Code not needed at all, because logic encapsulated into command
    //public char Code { get; set; }         
    public abstract void Action(IClient client);
}

public abstract class BaseCommand<T> : BaseCommand
{
    public T value { get; set; }
}

public class CommandA : BaseCommand<int>
{            
    public override void Action(IClient client)
    {        
        client.someInt = value * 2;
    }
}

public class CommandB : BaseCommand<string>
{
    public override void Action(IClient client)
    {
        client.someString = value.Trim();
    }
}

public interface IClient
{
    void CommandReceivedHandler(object sender, BaseCommand command);    
    int someInt { get; set; }
    string someString { get; set; }
}

public class Client : IClient
{
    public void CommandReceivedHandler(object sender, BaseCommand command)
    {
        command.Action(this);
    }

    public int someInt { get; set; }
    public string someString { get; set; }
}
 类似资料:
  • 问题内容: Command模式具有一个IReceiver接口,该接口带有很少的方法,并且与每个方法相对应的都是具体的Command对象(使用execute()方法实现接口)。 我了解到,客户端了解具体的接收方和具体命令,通常是客户在具体的命令对象中设置接收方对象。那么为什么说它使发送者和接收者分离呢? 当客户端已经知道具体的接收方时,我认为这并不是松散的耦合,并且在这种情况下,客户端也可以直接在接

  • 问题内容: 有人可以帮助我使用Python中的AT命令发送和接收SMS吗? 万一重要,我正在使用Fedora 8。 哪款手机搭配Linux(诺基亚,索尼爱立信,三星等)会更好?所有电话都支持使用AT命令发送和接收SMS吗? 问题答案: 以下是一些示例代码,可以帮助您入门(在Python 3000中): 您还需要做两件事: 用适当的格式编码消息(主要是GSM 03.38,unicode.org上有一

  • 我一直在试图找到一种方法,从我的PC(Windows 7)向Arduino Uno R3发送串行命令。我一直在做这个简单的程序,你应该通过USB电缆发送一个简单的“1”,以便打开车载LED。我的Arduino代码应该可以工作(我知道的,但我会确保上传它)。我一直在尝试使用Python和pySerial发送此命令,但我似乎无法让pySerial正常工作。我也尝试过使用CMD,但当我输入命令(ECHO

  • 7 宏命令        宏命令(Macro Command)又称为组合命令,它是组合模式和命令模式联用的产物。宏命令是一个具体命令类,它拥有一个集合属性,在该集合中包含了对其他命令对象的引用。通常宏命令不直接与请求接收者交互,而是通过它的成员来调用接收者的方法。当调用宏命令的execute()方法时,将递归调用它所包含的每个成员命令的execute()方法,一个宏命令的成员可以是简单命令,还可以

  • 6 请求日志        请求日志就是将请求的历史记录保存下来,通常以日志文件(Log File)的形式永久存储在计算机中。很多系统都提供了日志文件,例如Windows日志文件、Oracle日志文件等,日志文件可以记录用户对系统的一些操作(例如对数据的更改)。请求日志文件可以实现很多功能,常用功能如下:        (1) “天有不测风云”,一旦系统发生故障,日志文件可以为系统提供一种恢复机制

  • 5 撤销操作的实现        在命令模式中,我们可以通过调用一个命令对象的execute()方法来实现对请求的处理,如果需要撤销(Undo)请求,可通过在命令类中增加一个逆向操作来实现。 扩展 除了通过一个逆向操作来实现撤销(Undo)外,还可以通过保存对象的历史状态来实现撤销,后者可使用备忘录模式(Memento Pattern)来实现。        下面通过一个简单的实例来学习如何使用命