js设计模式之状态模式

一、简单介绍

状态模式的关键是区分事物内部的状态,事物内部状态的改变往往会带来事物的行为改变。

总的来说,状态模式就是封装状态,允许一个对象在其内部状态改变时改变它的行为,我们之前一般都是封装行为。

二、使用场景

在一些场景中,我们会定义一些状态,根据状态去执行不同的操作。比如,一个表单,初始状态有个编辑按钮,表单是只读的。点了编辑之后,表单变为可编辑,同时编辑按钮消失,出现了保存和取消按钮。点保存或者取消之后,回到初始状态。又或者,有一个开关控制关闭状态,点一下,变为打开状态;再点一下,变为关闭状态。

传统做法,我们是在点击事件里面写if else,但是,如果状态的种类增加了怎么办?我们需要修改原来的方法,去多写一些条件分支,同时增加对应的处理逻辑,这样显得不是很优雅。所以,状态模式就派上用场了。

三、示例

假设有这么一个场景。我们在界面有两个按钮,第一个按钮表示状态的切换,每点击一次,进入下一个状态。第二个方法点击之后执行对应的逻辑。假设我们现在4个状态,按钮背景颜色对应是黑色,透明度为0,0.3,0.6,1.以vue为例,来写一下大概的逻辑。

<template>
  <div>
    <div class="state-button" :style="getStyle" @click="state.changeState">切换状态</div>
    <a-button class="state" @click="state.handle">执行逻辑</a-button>
  </div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
import { getWeekdayConfig } from "./http";
interface StateHandle {
  value: number;
  handle: Function;
  changeState: Function;
}
@Component({})
export default class State extends Vue {
  public changeState(state: keyof State) {
    this.state = this[state];
  }
  public firstHandler() {
    //状态逻辑
    console.log("satate first");
  }
  public secondHandler() {
    //状态逻辑
    console.log("satate second");
  }
  public thirdHandler() {
    //状态逻辑
    console.log("satate third");
  }
  public forthHandler() {
    //状态逻辑
    console.log("satate forth");
  }
  public firstState: StateHandle = {
    value: 0,
    handle: this.firstHandler,
    changeState: this.changeState.bind(this, "secondState")
  };
  public secondState: StateHandle = {
    value: 0.3,
    handle: this.secondHandler,
    changeState: this.changeState.bind(this, "thirdState")
  };
  public thirdState: StateHandle = {
    value: 0.6,
    handle: this.thirdHandler,
    changeState: this.changeState.bind(this, "forthState")
  };
  public forthState: StateHandle = {
    value: 1,
    handle: this.forthHandler,
    changeState: this.changeState.bind(this, "firstState")
  };
  //   public changeState() {}
  public state: StateHandle = this.firstState;

  public get getStyle() {
    return {
      background: `rgba(0,0,0,${this.state.value})`
    };
  }
}
</script>
<style lang="less" scoped>
.state-button {
  display: inline-block;
  padding: 5px 12px;
  border: 1px solid #eee;
  box-sizing: border-box;
  cursor: pointer;
}
</style>

在上面的示例中,我们定义了四个状态,每个状态都有相同的接口,并把状态切换的功能放在了状态对象内部。我们需要执行的逻辑也放在各自的状态对象内部。这样一来,每个状态自己的逻辑和属性就维护在状态内部了,状态切换的顺序也由相关状态对象自己来控制。

如果是在普通项目里,我们可以把所有状态放在一个大的对象里,这个对象称作我们的状态机,我们需要做的就是定义好我们的状态机。

四、拓展

状态模式和之前提到的策略模式很相似,都是根据条件的不同,去执行对应的逻辑。它们的区别是,策略模式中的各个策略类,或者说条件,是互相独立且平行的,各个条件之间没有直接的关系,我们可以随时切换条件,在状态模式中,各个状态之间的切换规则是开始就被定义好的。改变状态发生在各个状态类的内部,一般的话不应该在外部去修改我们维护的状态。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值