前端:State(状态模式)

State(状态模式)属于行为型模式。

意图:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

简单来说,就是将 “一个大 class + 一堆 if else” 替换为 “一堆小 class”。一堆小 class 就是一堆状态,用一堆状态代替 if else 会更好拓展与维护。

举例子

如果看不懂上面的意图介绍,没有关系,设计模式需要在日常工作里用起来,结合例子可以加深你的理解,下面我准备了三个例子,让你体会什么场景下会用到这种设计模式。

团队接口人

团队是由很多同学组成的,但有一位接口人 TL,这位 TL 可能一会儿和产品经理谈需求,一会儿和其他 TL 谈规划,一会儿和 HR 谈人事,总之要做很多事情,很显然一个人是忙不过来的。TL 通过将任务分发给团队中每个同学,而不让他们直接和产品经理、其他 TL、HR 接触,那么这位 TL 的办事效率就会相当高,因为每个同学只负责一块具体的业务,而 TL 在不同时刻叫上不同的同学,让他们出面解决他们负责的专业领域问题,那么在外面看,这位 TL 团队能力很广,在内看,每个人负责的事情也比较单一。

台灯按钮

我们经常会看到只有一个按钮的台灯,但是可以通过按钮调节亮度,大概是如下一个循环 “关 -> 弱光 -> 亮 -> 强光 -> 关”,那么每次按按钮后,要跳转到什么状态,其实和当前状态有关。我们可以用 if else 解决这个问题,也可以用状态模式解决。

用状态模式解决,就是将这四个状态封装为四个类,每个类都执行按下按钮后要跳转到的状态,这样未来新增一种模式,只要改变部分类即可。

数据库连接器

在数据库连接前后,这个连接器的状态显然非常不同,我们如果仅用一个类描述数据库连接器,则内部免不了写大量分支语句进行状态判断。那么此时有更好的方案吗?状态模式告诉我们,可以创建多个不同状态类,比如连接前、连接中、连接后三种状态类,在不同时刻内部会替换为不同的子类,它们都继承同样的父类,所以外面看上去不需要感知内部的状态变化,内部又可以进行状态拆分,进行更好的维护。

意图解释

意图:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

重点在 “内部状态” 的理解,也就是状态改变是由对象内部触发的,而不是外部,所以 外部根本无需关心对象是否用了状态模式,拿数据库连接器的例子来说,不管这个类是用 if else 堆砌的,还是用状态模式做的,都完全不妨碍它对外提供的稳定 API(接口问题),所以状态模式实质上是一种内聚的设计模式。

结构图

  • State: 状态接口,类比为台灯状态。
  • ConcreteState: 具体状态,都继承于 State,类比为台灯的强光、弱光状态。

代码例子

下面例子使用 typescript 编写。

abstract class Context {
  abstract setState(state: State): void;
}

// 定义状态接口
interface State {
  // 模拟台灯点亮
  show: () => string
}

interface Light {
  click: () => void
}

type LightState = State & Light

class TurnOff implements State, Light {
  context: Context;

  constructor(context: Context) {
    this.context = context
  }

  show() {
    return '关灯'
  }

  // 按下按钮
  public click() {
    this.context.setState(new WeakLight(this.context))
  }
}

class WeakLight implements State, Light {
  context: Context;

  constructor(context: Context) {
    this.context = context
  }

  show() {
    return '弱光'
  }

  // 按下按钮
  public click() {
    this.context.setState(new StandardLight(this.context))
  }
}

class StandardLight implements State, Light {
  context: Context;

  constructor(context: Context) {
    this.context = context
  }

  show() {
    return '亮'
  }

  // 按下按钮
  public click() {
    this.context.setState(new StrongLight(this.context))
  }
}

class StrongLight implements State, Light {
  context: Context;

  constructor(context: Context) {
    this.context = context
  }

  show() {
    return '强光'
  }

  // 按下按钮
  public click() {
    this.context.setState(new TurnOff(this.context))
  }
}

// 台灯
class Lamp extends Context {
  // 当前状态
  #currentState: LightState = new TurnOff(this)
  setState(state: LightState) {
    this.#currentState = state
  }
  getState() {
    return this.#currentState
  }

  // 按下按钮
  click() {
    this.getState().click()
  }
}

const lamp = new Lamp() // 关闭
console.log(lamp.getState().show()) // 关灯
lamp.click() // 弱光
console.log(lamp.getState().show()) // 弱光
lamp.click() // 亮
console.log(lamp.getState().show()) // 亮
lamp.click() // 强光
console.log(lamp.getState().show()) // 强光
lamp.click() // 关闭
console.log(lamp.getState().show()) // 关闭

其实有很多种方式来实现,不必拘泥于形式,大体上只要保证由多个类实现不同状态,每个类实现到下一个状态切换就好了。

弊端

该用 if else 的时候还是要用,不要但凡遇到 if else 就使用状态模式,那样就是书读傻了。一定要判断,是否各状态间差异很大,且使用状态模式后维护性比 if else 更好,才应该用状态模式。

总结

在合适场景下,状态模式可以使代码更符合开闭原则,每个类独立维护时,逻辑也更精简、聚焦,更易维护。

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=17843,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?