Làm thế nào một máy trạng thái con có thể từ bỏ quyền kiểm soát trở lại máy trạng thái cha mẹ?


9

Máy trạng thái cấp cao nhất của tôi có một số trạng thái và các cạnh. Tôi sẽ gọi đây là máy trạng thái cha mẹ.

A ----> B ----> C

Bất kỳ trạng thái nào trong máy trạng thái cha cũng có thể là một máy trạng thái. Tôi sẽ gọi những đứa trẻ nhà nước máy.

           ___________
         /            \
A ----> |  B0->B1->B2  | ----> C
         \____________/

Nếu máy trạng thái mẹ chuyển từ A sang B, máy trạng thái của B sẽ tiếp quản. Khi B đã chạy xong, làm thế nào để từ bỏ quyền kiểm soát đối với máy trạng thái cha và chuyển sang trạng thái C? Bạn sử dụng mẫu thiết kế nào?

Nếu bạn đang tự hỏi, tôi có các máy trạng thái con trong các máy trạng thái cha mẹ vì dự án chính xác của tôi khá phức tạp và việc đóng gói các hoạt động bên trong của trạng thái con là điều tự nhiên.


Tôi đoán rằng B0, B1 và ​​B2 nên biết rằng chúng là thành phần của một thứ gì đó mà thế giới bên ngoài coi là một đơn vị. Vì vậy, có lẽ bạn phải có một MachineContainerlớp Bchứa B0, B1 và ​​B2 và khi B2 kết thúc, nó sẽ chuyển điều khiển trở lại vùng chứa của nó, sau đó chuyển sang C ... Tôi thực sự chưa bao giờ thử bất cứ thứ gì như thế này. Đó là một vấn đề thú vị!
Thất vọngWithFormsDesigner

2
Câu hỏi của bạn có câu trả lời rõ ràng hoặc câu hỏi của bạn không rõ ràng lắm. Theo quan điểm của phụ huynh, bạn nên thực hiện chính xác như bạn sẽ thực hiện một máy trạng thái không có máy trạng thái con. Nó chỉ xảy ra rằng các trạng thái được thực hiện bằng cách sử dụng các máy trạng thái con nhưng điều đó hoàn toàn không ảnh hưởng đến cha mẹ. Nó cũng không nên ảnh hưởng đến các máy trạng thái trẻ em ngoài khi thoát ra, chúng chỉ tạo ra các sự kiện cấp cha mẹ.
Dunk

Câu trả lời:


5

Mỗi máy trạng thái có một số loại xử lý sự kiện và một phương tiện để kích hoạt các sự kiện đó. Trình xử lý đó lấy làm đầu vào trạng thái và loại sự kiện hiện có, chọn trạng thái mới và tùy ý chạy một số mã hiệu ứng phụ.

Về cơ bản, trong khi ở trạng thái B, trình xử lý sự kiện chính của bạn chuyển tiếp bất kỳ sự kiện nào mà nó không nhận ra đối với Btrình xử lý sự kiện và vẫn ở trạng thái B. Khi Bmuốn chuyển sang C, nó đăng sự kiện thích hợp đến trình xử lý sự kiện chính.


2

Bạn đã đọc phần này của Taoup chưa? Có một số cách khác nhau để thực hiện điều này nhưng nhiều cách trong số đó phụ thuộc vào cách bạn phân chia các máy trạng thái của mình. Có phải chúng là các quá trình riêng biệt? Chủ đề? Các đối tượng?

Chỉ ra cách bạn xây dựng chúng và xem liệu có cách nào để chúng giao tiếp với nhau không. Nếu một cái không tồn tại, bạn có thể đang thiết kế hệ thống của bạn sai.

Đối với tôi, tôi sẽ xem xét các quy trình riêng biệt, nối stdin và stdout với nhau. Máy trạng thái con sau đó trở nên độc lập, hoạt động trên stdin và xuất ra trên thiết bị xuất chuẩn. Nó trở thành công việc của máy trạng thái cha mẹ để bắt đầu quá trình con, nối các đường ống và sau đó đổ dữ liệu và chờ kết quả. Tất cả những điều đó đã được thực hiện trong tất cả các ngôn ngữ hiện đại, vì vậy nó rất dễ thực hiện.


1

Tách hai máy trạng thái và sử dụng tin nhắn chuyển qua lại giữa chúng. Do đó, máy trạng thái 1 sẽ tiến hành từ ABC, trong đó ở trạng thái B, nó sẽ kiểm tra kết quả hiện tại từ máy trạng thái 2. Nếu đầu ra thay đổi, thì máy trạng thái 1 có thể giải thích cho nó và máy trạng thái 2 không cần có bất kỳ nhận thức nào làm thế nào máy trạng thái 1 thực sự hoạt động. Cái gì đó như:

typedef struct StateMachine {
  void(*Update)(); // function to update the state machine
  int Data;        // generic temp holder to survive state contexts
  int State;       // current state of our state machine
  int *Message;    // pointer to a shared integer for message passing
};

int main(void) {
  int Message = 0;
  /* NewStateMachine would malloc the struct, pass in the int reference
   * and function pointer as well as add it to a circularly linked list */
  NewStateMachine(&Message, MainLoop);
  NewStateMachine(&Message, MinorLoop);
  StateMachine *Current = StateMachine_CLL.First;

  for(;;) {
    Current->Update(Current); /* Update the current state machine */
    Current = Current->Next;  /* And the advance to the next one */
  }
}

void MainLoop(StateMachine *this) {
  switch(this.State) {
  case 0:
    CloseCoolantTank(1); /* safe to call if valve already closed */
    CloseCoolantTank(2); /* safe to call if valve already closed */
    this.State = 1;
    break;
  case 1:
    /* we have a message, do something */
    if(*this.Message) this.State = 2;          
    /* otherwise stall at this state until we get a message */
    else this.State = 1;          
    break;
  case 2:
    if(*this.Message == 1) this.State = 3;      /* warm */
    else if(*this.Message == 2) this.State = 4; /* hot! */
    else this.State = 0;                        /* cooled down, shut off valves */
    this.Message = 0;                           /* clear the message */
    break;
  case 3:
    OpenCoolantTank(1); /* opens the valve, safe to call if already open */
    this.State = 2;     /* recheck for new message */
    break;
  case 4:
    OpenCoolantTank(2); /* opens the valve, safe to call if already open */
    this.State = 3;     /* also open coolant tank 1 for extra cooling */
    break;
  }
}

/* Monitor temperature and send messages on overheat */
void MinorLoop(StateMachine *this) {
  switch(this.State) {
  case 0:
    this.Data = ReadADCValue();
    this.State = 1;
    break;
  case 1:
    if(this.Data > 150) *this.Message = 2;
    else if(this.Data > 100) *this.Message = 1;
    this.State = 0;
    break;
  }
}

1

Giải pháp phụ thuộc vào 1) liệu các trạng thái phụ của A có thể nhìn thấy các trạng thái phụ của B hay không. 2) Do AB và C xuất phát từ cha mẹ chung. Nếu họ có cha mẹ chung và khả năng hiển thị là phổ quát, bạn không nên gặp quá nhiều khó khăn khi chuyển từ trạng thái phụ của B sang trạng thái phụ của A.

Nếu bạn đã cách ly chúng thông qua các không gian tên và / hoặc A, B và C không có cha mẹ chung, thì cách tốt nhất của bạn là sử dụng trình điều khiển thay đổi trạng thái bên ngoài cho các máy A, B và C. Điều này có thể được thực hiện thông qua một xử lý sự kiện. Đơn giản chỉ cần có một người quan sát trong A có thể lắng nghe các sự kiện được nêu trong B và chuyển sang trạng thái phụ của chính nó dựa trên sự kiện đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.