设计模式-状态模式

前言

状态模式应用比较广泛,根据状态改变行为,可以说在我们代码中常常会用到,状态机也是基于如此实现,比如我们想根据状态更改class等等。以下是一个控制灯开关的demo

function Light(){
  this.state = "off";
  this.button = null;
}
Light.prototype.init = function(){
  const button = document.createElement("button");
  button.innerHTML = "开关";
  this.button = document.appendChild(button);
  const _self = this;
  this.button.addEventListener("click",function(){
    _self.buttonPress();
  },false);
}
Light.prototype.buttonPress = function(){
  if(this.state==="off"){
    console.log("灯打开了!");
    this.state = "turn";
  }else{
    console.log("灯关上了!");
    this.state = "off";
  }
}

上述代码完成任务完全没问题,但是如果此时需要增加几个状态,比如弱光、强光,我们势必会添加很多很多if…else,并且会深入逻辑内部,这显然是不符合开放-封闭原则的。上述代码,在我之前写的程序中也会非常多,这时我们需要使用状态模式对状态进行管理

JavaScript中的状态模式

状态模式强调将状态封装为类,我们平常都是将行为进行封装,而状态模式是对属性(状态)进行封装,这样状态就不会与逻辑进行耦合,我们更换、添加状态时就会更加的方便,现在使用状态模式对开关灯demo进行改写

function Light() {
  this.Turn = new Turn(this);
  this.Off = new Off(this);
  this.button = null;
}
/*  打开状态  */
function Turn(light) {
  this.light = light;
}
Turn.prototype.buttonPress = function () {
  console.log("灯关上了!");
  // 当前状态为关闭
  this.light.setState(this.light.Off);
}
/*  关闭状态  */
function Off(light) {
  this.light = light;
}
Off.prototype.buttonPress = function () {
  console.log("灯开上了!");
  // 当前状态为打开
  this.light.setState(this.light.Turn);
}

Light.prototype.init = function () {

  const button = document.createElement("button");
  button.innerHTML = "开关";
  this.button = document.body.appendChild(button);
  this.currState = this.Off;
  const _self = this;
  this.button.addEventListener("click", function () {
    _self.currState.buttonPress();
  }, false);
}
Light.prototype.setState = function (newState) {
  this.currState = newState;
}

const light = new Light();
light.init();

一个状态就是一个类,这时我们想添加状态只需要增加一个状态类,修改一部分逻辑即可(顺序和在内部实例化一个状态类)。所有状态类都需要实现相应的触发方法,在本例中为buttonPress,这在面向对象语言中使用抽象类即可


public abstract class State {
	abstract void buttonPress();
}

但是在JavaScript中并没有接口或者抽象类的概念,所以我们可以使用抛出错误的形式人为的规定,必须实现相应的方法

function State(){ }
State.prototype.buttonPress = function(){
  throw new Error("必须重写buttonPress方法");
}
function Turn(light){
  this.light = light;
}
Turn.prototype = new State();

状态机

状态机是一种统一管理状态的实现,在JavaScript中实现状态机非常的容易,并且实用

/*  状态机  */
const FSM = {
  off:{
    buttonPress(){
      console.log("灯开上了!");
      this.currState = FSM.on;
    }
  },
  on:{
    buttonPress(){
      console.log("灯关上了!");
      this.currState = FSM.off;
    }
  }
}
function Light() {
  this,currState = FSM.off;
  this.button = null;
}

Light.prototype.init = function () {

  const button = document.createElement("button");
  button.innerHTML = "开关";
  this.button = document.body.appendChild(button);
  const _self = this;
  this.button.addEventListener("click", function () {
    _self.currState.buttonPress();
  }, false);
}


const light = new Light();
light.init();

优缺点

状态模式将动作与相应的行为和状态进行解耦,但是会添加比较多的状态类,并且状态之间是耦合在一起的,如果想修改顺序还是需要深入代码内部,状态机对所有状态进行管理,在JavaScript中更加容易实现和实用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值