2017-04-10 1 views
2

저는 직장 동료가 프로그래밍 한 펌웨어로 직렬로 명령을 보내고 받아야하는 데스크톱 응용 프로그램과 함께 작업하고 있습니다.명령 패턴을 사용하여 직렬로 명령을 보내고 받으십시오.

명령 유형이 ASCII 문자로 표시되고 각 명령 유형에 페이로드 (명령 유형간에 임의적이지만 각 유형에 대해 고정되어 있음)가 포함될 수있는 프로토콜을 고안했으며 명령은 대괄호로 묶었습니다. 게터의> 현재 일련 번호를 알리기 위해 새로운 일련 번호를 저장하거나 PC에 장치하는 장치로 PC VROM 전송 (종류 -

  • 예를 들어, 우리는 다음의 커멘드를/setter 명령);
  • [R] - "get serial"명령을 요청하기 위해 PC에서 장치로 보냈습니다.
  • [A12] - 기기에서 PC로 전송되어 새로운 ADC 읽기를 알립니다.
  • [B] - 배터리 충전을 요청하기 위해 PC에서 장치로 전송 됨.
  • `[B89] - 배터리 충전을 알리기 위해 장치에서 PC로 보냄;

그래서이 수신하고 수신 바이트를 구문 분석하고, 명령이 성공적으로 구문 분석 할 때마다이 이벤트는 다음과 같은 임시 서명으로 제기되는 클래스 :

internal event EventHandler<SerialCommand> CommandReceived; 

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 이벤트 소비자).
+0

어쩌면 간단한지도가 당신을 도울 수를이 게시물에, http://stackoverflow.com/questions/43035984/what-design-의 마지막 대답을 확인 pattern-is-for-this-situation – dstar55

답변

2

당신은이 같은 시도 할 수 있습니다 :

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

필자는 여러분이 명령 인스턴스에 클라이언트 인스턴스를 제공하는 방식이 마음에 들었다. 필자는 이것이 명령 패턴이 클라이언트 인스턴스 또는 클라이언트 metod를 명령에 전달함으로써 사용되는 방법이라고 생각합니다. – heltonbiker

+0

사실 저는 액션 호출이 아닌 생성자를 통해 클라이언트에 전달하는 변형과 함께 갈 것이라고 생각합니다. 어쨌든 협력은 동등합니다. 감사! – heltonbiker

관련 문제