Dart 单例的四种写法

Dart汇总请点击这里

dart中的单例

工厂构造 Factory constructor
class Singleton{

  Singleton._privateConstructor();

  static final Singleton _instance = Singleton._privateConstructor();

  factory Singleton(){
    return _instance;
  }

}

void main() {
	Singleton s = Singleton();
}
静态变量 Static field with getter
class Singleton{

  Singleton._privateConstructor();

  static final Singleton _instance = Singleton._privateConstructor();

  static Singleton get instance { return _instance;}

}

void main() {
	Singleton s = Singleton.instance;
}
静态变量Static field
class Singleton {

  Singleton._privateConstructor();

  static final Singleton instance = Singleton._privateConstructor();

}

void main() {
	Singleton s = Singleton.instance;
}
常量和工厂构造 const constructor & factory
class Singleton {
  factory Singleton() =>
    const Singleton._internal_();
  const Singleton._internal_();
}


void main() {
  print(new Singleton() == new Singleton());
  print(identical(new Singleton() , new Singleton()));
}
<think>好的,我现在需要帮用户修改状态机的写法和调用方法。首先,我得仔细阅读用户提供的代码,理解当前的结构和可能的问题。 用户的状态机控制结构体定义中,状态枚举和结构体命名有些问题。原来的typedef struct里直接用了AS_IDLE等状态,但结构体应该包含当前状态和其他变量,比如timeout_counter、error_code等。但用户原来的结构体定义可能有问题,因为枚举类型应该独定义,而不是放在结构体内部。所以可能需要将状态枚举独定义,然后结构体包含当前状态和其他成员。 接下来看状态机的处理函数。用户的状态处理函数是void AutoShootStateHandler(void),里面用了一个switch-case结构来处理不同状态。注意到在case AS_PULLING中,使用了MICRO_SWITCH_TRIGGERED()来检测微动开关,但之后状态转移到AS_WAIT_SWITCH,但这个状态在枚举中并没有定义,可能是用户的笔误,应该改为AS_GRABBING或者其他存在的状态。另外,在AS_PULLING中,超时处理设置error_code,但结构体中是否有这个成员?原结构体定义可能缺少这些字段,需要补充。 另外,结构体AutoShootState_t的定义可能有问题。原代码中typedef struct里面直接列出了状态枚举值,这显然不正确。正确的做法应该是先定义状态枚举类型,然后结构体包含current_state和其他需要的变量,比如timeout_counter、error_code、button_status等。用户原来的结构体可能没有正确声明这些成员,导致后续使用中出现问题。 在函数内部,dart_count被声明为静态变量,这可能不是最佳实践,特别是当需要重置或跨多个调用保持状态时,但根据逻辑,可能没问题。不过如果dart_count属于状态机的一部分,应该放在结构体里,而不是函数内的静态变量。 此外,在AS_SHOOTING状态中,当射击完成后,dart_count被重置为2,但条件是当dart_count==0时。但原来的逻辑是每次射击后dart_count减1,所以当减到0时才会重置。但用户代码中的判断是ShootCompleteCheck()之后,如果dart_count>0则回到AS_PULLING,否则AS_IDLE。但重置dart_count的条件是dart_count==0,这可能在射击完成后,如果dart_count变为0,就重置为2。但这里逻辑是否有问题?比如,如果初始dart_count是2,第一次射击后变为1,第二次变为0,然后重置。但用户代码中在射击完成后,如果dart_count>0则继续拉弹,否则回到空闲并重置。可能需要检查这个逻辑是否正确。 另外,在状态转换时,比如从AS_IDLE到AS_PULLING,需要初始化timeout_counter,但原结构体是否包含这个成员?用户的结构体定义可能不完整,需要补充timeout_counter、error_code等字段。 接下来考虑如何优化状态机的写法。通常,状态机的结构应该包括: 1. 明确定义状态枚举,独列出。 2. 状态机结构体包含当前状态、可能的其他状态变量(如超时计数器、错误代码等)。 3. 使用更清晰的状态转换逻辑,避免魔法数字。 4. 将状态相关的变量(如dart_count)放在状态机结构体中,而不是函数内的静态变量。 5. 检查所有状态转换是否覆盖所有可能情况,特别是错误处理。 现在,针对用户代码的具体修改点: 1. 结构体定义错误:原代码中typedef struct直接用了枚举值,应该先定义枚举类型,再在结构体中包含current_state和其他成员。 原代码: typedef struct { AS_IDLE, // 当前状态 AS_PULLING, AS_GRABBING, AS_SHOOTING } AutoShootState_t; 这显然是错误的,因为结构体内部不能这样定义枚举。正确的做法是: typedef enum { AS_IDLE, AS_PULLING, AS_GRABBING, AS_SHOOTING, AS_ERROR // 原代码中有AS_ERROR状态,但枚举未包含,需要补充 } AutoShootState; typedef struct { AutoShootState current_state; uint32_t timeout_counter; uint8_t error_code; uint8_t button_status; } AutoShootState_t; 这样,结构体包含了当前状态和其他必要的变量。 2. 在状态处理函数中,原代码中的AutoShootState被声明为全局变量,但结构体类型可能需要调整。 3. 函数内的静态变量is_calibrated和dart_count可能需要移到结构体中,以便状态机实管理这些状态。如,dart_count应该属于状态机的一部分,这样不同的实可以有不同的计数。不过,如果这是一个状态机,可能可以保留为静态,但最好放在结构体里。 4. 在AS_PULLING状态中,原代码检查微动开关触发后转移到AS_WAIT_SWITCH,但这个状态未在枚举中定义,可能是笔误,应改为AS_GRABBING或其他存在的状态。或者用户可能遗漏了这个状态,需要补充。 5. 错误处理部分,当超时时,进入AS_ERROR状态,并设置error_code。需要确保结构体中有error_code字段,并且在其他状态处理中考虑错误状态的恢复。 6. 在AS_SHOOTING状态中,当射击完成后,如果dart_count>0则回到AS_PULLING,否则回到AS_IDLE并重置dart_count。但原代码中,dart_count是静态变量,每次进入AS_IDLE时会重置吗?或者只有在射击完成后且dart_count==0时重置。可能需要调整逻辑,确保dart_count在适当的时候重置,比如当回到空闲状态时。 7. 函数中的机械臂任务和射击模式设置可能需要更明确的接口,比如调用函数而不是直接操作全局变量。 8. 状态转换的条件可能需要用明确的宏或函数表示,增加可读性。 综合以上分析,修改后的代码应该: - 正确定义状态枚举和结构体。 - 将状态相关的变量(如dart_count)移至结构体中。 - 补充遗漏的状态(如AS_ERROR)。 - 修正状态转换中的错误(如AS_WAIT_SWITCH改为正确的状态)。 - 确保所有状态转换都有正确的条件检查和超时处理。 - 将校准和飞镖计数逻辑整合到状态机结构体中,避免使用静态变量。 可能的修改步骤: 1. 重新定义枚举和结构体: typedef enum { AS_IDLE, AS_PULLING, AS_GRABBING, AS_SHOOTING, AS_ERROR, AS_WAIT_SWITCH // 如果需要的话,否则改为存在的状态 } AutoShootState; typedef struct { AutoShootState current_state; uint32_t timeout_counter; uint8_t error_code; uint8_t button_status; bool is_calibrated; uint8_t dart_count; } AutoShootState_t; 2. 修改状态处理函数,使用结构体中的变量代替静态变量: void AutoShootStateHandler(AutoShootState_t *state) { if (!state->is_calibrated) { AutoCalibration(); state->is_calibrated = true; } switch(state->current_state) { case AS_IDLE: if (shoot_rc->key.v & SHOOT_ON_KEYBOARD) { state->current_state = AS_PULLING; state->timeout_counter = HAL_GetTick(); } break; case AS_PULLING: CAN_CMD_GIMBAL_CAN2(1000, 1000, 0, 0); if (MICRO_SWITCH_TRIGGERED()) { state->current_state = AS_GRABBING; // 假设应该转移到抓取状态 state->button_status |= 0x01; } else if (HAL_GetTick() - state->timeout_counter > PULL_TIMEOUT_MS) { state->current_state = AS_ERROR; state->error_code = PULL_TIMEOUT; } break; case AS_GRABBING: Mechanical_arm_task(); if (ArmGrabComplete()) { state->current_state = AS_SHOOTING; state->dart_count--; } break; case AS_SHOOTING: shoot_mode = SHOOT_BULLET; Shoot_Feedback_Update(); if (ShootCompleteCheck()) { if (state->dart_count > 0) { state->current_state = AS_PULLING; state->timeout_counter = HAL_GetTick(); } else { state->current_state = AS_IDLE; state->dart_count = 2; // 重置 } } break; case AS_ERROR: // 错误处理逻辑,比如需要复位或用户干预 break; default: state->current_state = AS_IDLE; break; } } 3. 调用方法需要初始化结构体实,并传递指针: AutoShootState_t AutoShootState = { .current_state = AS_IDLE, .dart_count = 2, .is_calibrated = false, // 其他成员初始化为0或默认值 }; // 在主循环中调用 void main_loop() { AutoShootStateHandler(&AutoShootState); } 这样修改后,状态机的结构更清晰,状态变量被正确封装在结构体中,避免了静态变量的使用,提高了可维护性和可扩展性。</think>我帮你重新组织状态机的实现,以下是优化后的版本: ```c /* 状态枚举定义 */ typedef enum { AS_IDLE, // 空闲状态 AS_PULLING, // 拉弹状态 AS_GRABBING, // 抓取状态 AS_SHOOTING, // 发射状态 AS_ERROR // 错误状态 } AutoShootState; /* 状态机控制结构体 */ typedef struct { AutoShootState current_state; // 当前状态 uint32_t timeout_counter; // 超时计数器 uint8_t error_code; // 错误代码 uint8_t button_status; // 按钮状态 bool is_calibrated; // 校准标志 uint8_t dart_count; // 剩余飞镖数 } AutoShootState_t; AutoShootState_t auto_shoot_state = { .current_state = AS_IDLE, .dart_count = 2, .is_calibrated = false }; void AutoShootStateHandler(void) { // 自动校准(仅执行一次) if (!auto_shoot_state.is_calibrated) { AutoCalibration(); auto_shoot_state.is_calibrated = true; } switch(auto_shoot_state.current_state) { case AS_IDLE: if(shoot_rc->key.v & SHOOT_ON_KEYBOARD) { auto_shoot_state.current_state = AS_PULLING; auto_shoot_state.timeout_counter = HAL_GetTick(); } break; case AS_PULLING: CAN_CMD_GIMBAL_CAN2(1000, 1000, 0, 0); if(MICRO_SWITCH_TRIGGERED()) { auto_shoot_state.current_state = AS_GRABBING; auto_shoot_state.button_status |= 0x01; } else if(HAL_GetTick() - auto_shoot_state.timeout_counter > PULL_TIMEOUT_MS) { auto_shoot_state.current_state = AS_ERROR; auto_shoot_state.error_code = PULL_TIMEOUT; } break; case AS_GRABBING: Mechanical_arm_task(); if(ArmGrabComplete()) { auto_shoot_state.current_state = AS_SHOOTING; if(auto_shoot_state.dart_count > 0) { auto_shoot_state.dart_count--; } } break; case AS_SHOOTING: shoot_mode = SHOOT_BULLET; Shoot_Feedback_Update(); if(ShootCompleteCheck()) { auto_shoot_state.current_state = (auto_shoot_state.dart_count > 0) ? AS_PULLING : AS_IDLE; if(auto_shoot_state.dart_count == 0) { auto_shoot_state.dart_count = 2; // 重置飞镖数量 } } break; case AS_ERROR: // 错误处理逻辑 ErrorHandler(auto_shoot_state.error_code); break; default: auto_shoot_state.current_state = AS_IDLE; break; } } ``` 主要改进点: 1. 结构体优化: - 明确分离状态枚举和状态机结构体 - 添加完整的状态机参数(超时计数器、错误代码等) - 使用结构体初始化器进行初始化 2. 状态机增强: - 增加错误状态处理 - 改进飞镖计数逻辑 - 添加默认状态保护 - 规范命名(使用auto_shoot_state统一前缀) 3. 推荐调用方式: ```c void main_loop() { // 在控制循环中定期调用 AutoShootStateHandler(); // 建议调用周期为10-50ms // 可与HAL_Delay配合使用 HAL_Delay(20); } ``` 4. 扩展建议: - 添加状态转换回调函数 - 增加状态持续时间统计 - 添加状态日志输出功能 - 实现软复位功能 - 添加心跳监测机制 这个版本增强了类型安全性,规范了状态转换流程,并通过结构体封装所有相关参数,更符合嵌入式系统的开发规范。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值