当前位置:   article > 正文

小程序设计模式之状态模式实践-蓝牙配网_小程序 蓝牙状态模式

小程序 蓝牙状态模式

引言

相信大家在开发的过程中或多或少遇到过某些事件存在多种状态,不知道大家都是怎么处理的,是不是需要花大量时间去维护这些状态。随着物联网的普及,家电等产品的配网功能也越发普及。本文就以微信小程序蓝牙配网如何使用状态模式,因为配网涉及到多个状态。
  • 1

蓝牙配网

整个过程一般就是用户通过小程序搜索到设备,然后通过蓝牙连接上设备,再把家中的路由器信息发送给设备,最后设备通过收到的信息连上路由器,接入网络。
  • 1

状态机

我们先先来看看一般的做法
① 首先,我们找出蓝牙配网中的一些状态:
1. 蓝牙未连接
2. 蓝牙连接中
3. 蓝牙已连接
4. 路由信息已接收
5. WIFI连网中
6. 配网成功
② 然后,定义一些常量来指定各个状态:
const UNCONNECTED = 1;
const CONNECTING = 2;
const CONNECTED = 3;
const RECEIVED = 4;
const WIFI_CONNECTING = 5;
const WIFI_CONNECTED = 6;

let state = UNCONNECTED;

③ 最后我们创建一个状态机的类,比如在连接的函数里处理每个状态下的情况:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在这里插入图片描述
④ 使用状态机的类
在这里插入图片描述
这看起来没什么问题,也挺好用。但某次会议上,某人提出了现在的方式有缺陷,不是很安全,应该在蓝牙连接后进行设备的认证。最后领导拍板,在原来的基础上增加几个状态。
既然要更改,那就赶紧召集开发人员,结果开发人员一看,沃日要修改好多地方:
1.首先可能要增加两种新的状态:
const AUTHENTCATING = 7;
const AUTHENTCATED = 8;
2.然后在那些处理状态的方法里增加类似else if的东西,太多了,太多了。
就在程序员炸裂的边缘,你们的架构师瞄了眼说,怎么没有用状态模式,程序员一脸无奈的看着架构师。
好了题外话说到这,进入本次的正题——状态模式

什么是模式

模式是指在某种情境下,针对某问题的某种解决方案。
  • 1

何时用设计模式

在设计的时候,如果遇到某个问题,而且该问题不能用简单的设计就能解决,那么可以试着利用某个模式帮助我们解决那个问题。
  • 1

新的设计

我们把每个状态都看成一个对象,然后在动作发生时委托给当前状态。
首先,我们定义个抽象类State,在这个类内,蓝牙配网的每个动作都有一个对应的函数。
然后为每个状态实现状态类。这些类将负责对应状态下的行为。
最后,将动作委托到状态类。
  • 1
  • 2
  • 3
  • 4

重新定义State类

class AbstractState {
	constructor(stateController) {
    	this.stateController = stateController; // 状态控制类
  	}
	
	/**
   * 连接蓝牙设备
   * @see UnConnectState
   */
  connect() {}

  /**
   * 断开蓝牙设备
   * @see UnConnectState
   */
  disconnect() {}

  /**
   * 蓝牙连接成功
   * @see UnConnectState
   */
  connectSuccess() {}

  /**
   * 蓝牙连接失败
   * @see UnConnectState
   */
  connectFail() {}

  /**
   * 路由数据接收完成
   * @see ReceivedState
   */
  received() {}

  /**
   * 认证中
   * @see AuthenticatingState
   */
  authenticating() {}

  /**
   * 认证完成
   * @see AuthenticatedState
   */
  authenticated() {}

  /**
   * 充电完成
   * @see WifiConnectingState
   */
  wifiConnecting() {}

  /**
   * 时间同步完成
   * @see WifiConnectedState
   */
  wifiConnected() {}

  /**
   * 获取状态ID
   */
  getStateId() {
    return 0;
  }

  /**
   * 释放资源
   * @see ConnectedState
   */
  onRelease() {}
}

module.exports = AbstractState
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

实现各状态类

UnConnectState类

import AbstractState from './AbstractState'

class UnConnectState extends AbstractState { // 未连接状态只处理连接的事件
  constructor(stateController) {
    super(stateController);
  }

  /**
   * @override
   * @description 连接设备
   */
  connect() { // 这里只是实例,具体需要怎么处理还要更具体的业务逻辑
    const ble = this.stateController.getBLE();
    if (ble) {
      this.stateController.setState(this.stateController.getConnectingState());
      this.stateController.notifyAll();
      ble.initBleAdapter();
    }
  }

  getStateId() {
    return 100;
  }
}
module.exports = UnConnectState
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

ConnectingState类

import AbstractState from './AbstractState'

class ConnectingState extends AbstractState { // 蓝牙连接状态的类
  constructor(stateController) {
    super(stateController);
  }

  connectSuccess() {
    this.stateController.setState(this.stateController.getConnectedState());
    this.stateController.notifyAll();
  }

  connectFail() {
    this.stateController.setState(this.stateController.getUnConnectState());
    this.stateController.notifyAll();
  }

  disconnect() {
    this.stateController.setState(this.stateController.getUnConnectState());
    this.stateController.notifyAll();
  }

  getStateId() {
    return 101;
  }
}
module.exports = ConnectingState
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

ConnectedState类

import AbstractState from './AbstractState'

class ConnectedState extends AbstractState {
  constructor(stateController) {
    super(stateController);
  }

  connectFail() {
    this.stateController.setState(this.stateController.getUnConnectState());
    this.stateController.notifyAll();
    // 结束发送路由的命令
  }

  authenticating() {    this.stateController.setState(this.stateController.getAuthenticatingState());
    // 发送认证的指令
  }

  disconnect() {
    this.stateController.setState(this.stateController.getUnConnectState());
    this.stateController.notifyAll();
  }

  getStateId() {
    return 102;
  }

  onRelease() {
    
  }
}
module.exports = ConnectedState
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

由于篇幅,其他的状态类就不在这里写了。

StateController类

import UnConnectState from './UnConnectState';
import ConnectingState from './ConnectingState';
import ConnectedState from './ConnectedState';

const DEBUG = true;
const TAG = 'StateController#';

let mUnConnectState = null;
let mConnectingState = null;
let mConnectedState = null;
let mState = null;

let mBle = null;

let STATE_CONTROLLER = null;
/** 页面监听器列表 */
let mPageObservers = new Set();


class StateController {
  constructor() {
    mUnConnectState = new UnConnectState(this);
    mConnectingState = new ConnectingState(this);
    mConnectedState = new ConnectedState(this);
    mState = mUnConnectState;
  }

  static getInstance() {
    if (STATE_CONTROLLER == null) {
      STATE_CONTROLLER = new StateController();
    }
    return STATE_CONTROLLER;
  }

  addPage(page) {
    mPageObservers.add(page);
  }

  deletePage(page) {
    mPageObservers.delete(page);
  }

  clearPages() {
    mPageObservers.clear();
  }

  /**
   * 连接设备,在调用之前确保已经调用过#setDeviceId(deviceId)
   */
  connect() {  
    mState.connect();
  }

  /**
   * 断开设备连接
   */
  disconnect() {
    mState.disconnect();
  }

  /**
   * 设备连接成功
   */
  connectSuccess() {
    mState.connectSuccess();
  }

  /**
   * 设备连接失败
   */
  connectFail() {
    mState.connectFail();
  }

  /**
   * 设置状态
   * @param {*} state 需要设置的状态
   * @see UnConnectState
   * @see ConnectingState
   * @see ConnectedState
   */
  setState(state) {
    mState = state;
  }

  /**
   * 释放状态资源
   */
  onRelease() {
    mState.onRelease();
  }

  /**
   * 页面退出
   */
  onUnload() {
    this.disconnect();
    this.onRelease();
  }

  getState() {
    return mState;
  }

  getUnConnectState() {
    return mUnConnectState;
  }

  getConnectingState() {
    return mConnectingState;
  }

  getConnectedState() {
    return mConnectedState;
  }


  getStateId() {
    return mState.getStateId();
  }


  getBLE() {
    if (mBle == null)
      mBle = BLE.getInstance();
    return mBle;
  }

  notifyAll() {
    this.notifyState(mState.getStateId());
  }

  /**
   * 通知页面当前的状态
   * @param {*} status 
   */
  notifyState(status) {
    mPageObservers.forEach((pageObserver) => {
      pageObserver(status);
    });
  }

}

module.exports = StateController
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145

使用新的设计

import State from './state'
import StateController from './StateController'
class StateTest {
  constructor() {}

  onClick() {
    // let state = new State();
    // state.connectBLE();
    let stateController = StateController.getInstance();
    stateController.connect();
  }
}

module.exports = StateTest;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

通过新的设计,我们可以看到一些变化:
1.将每个状态的行为局部化到了它自己的类中;
2.去掉了很多的ifelse语言;
3.方便扩展,可增删状态,对每个状态来说是“对修改关闭”。

状态模式定义

状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
  • 1

状态模式类图

在这里插入图片描述

总结

  1. 状态模式用类代表状态;
  2. 使用状态模式会增加类的数目,但这是为了更好的扩展和弹性;
  3. 状态的转换可以由各状态(State)改变,也可以由Context类控制,比如示例中的StateController。

如需转载请注明原地址

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/321146
推荐阅读
相关标签
  

闽ICP备14008679号