赞
踩
相信大家在开发的过程中或多或少遇到过某些事件存在多种状态,不知道大家都是怎么处理的,是不是需要花大量时间去维护这些状态。随着物联网的普及,家电等产品的配网功能也越发普及。本文就以微信小程序蓝牙配网如何使用状态模式,因为配网涉及到多个状态。
整个过程一般就是用户通过小程序搜索到设备,然后通过蓝牙连接上设备,再把家中的路由器信息发送给设备,最后设备通过收到的信息连上路由器,接入网络。
我们先先来看看一般的做法 ① 首先,我们找出蓝牙配网中的一些状态: 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.首先可能要增加两种新的状态:
const AUTHENTCATING = 7;
const AUTHENTCATED = 8;
2.然后在那些处理状态的方法里增加类似else if的东西,太多了,太多了。
就在程序员炸裂的边缘,你们的架构师瞄了眼说,怎么没有用状态模式,程序员一脸无奈的看着架构师。
好了题外话说到这,进入本次的正题——状态模式
模式是指在某种情境下,针对某问题的某种解决方案。
在设计的时候,如果遇到某个问题,而且该问题不能用简单的设计就能解决,那么可以试着利用某个模式帮助我们解决那个问题。
我们把每个状态都看成一个对象,然后在动作发生时委托给当前状态。
首先,我们定义个抽象类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
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
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
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
由于篇幅,其他的状态类就不在这里写了。
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
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.去掉了很多的ifelse语言;
3.方便扩展,可增删状态,对每个状态来说是“对修改关闭”。
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
如需转载请注明原地址
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。