允许对象在内部状态改变时,改变它的行为

大厅灯光

在酒店的大厅里面是会有一个开关控制灯光、一般情况下一个开关可以控制一个灯光很多场景,比如按一下是打开微弱灯光、再按一下变成强光、继续再来一下灯光被关闭、所以我们很容易写出下方代码

一梭子写法

  1. class Light{
  2. constructor(){
  3. this.state = 'off'
  4. }
  5. buttonWasPressed(){
  6. if(this.state === 'off'){
  7. console.log('弱光')
  8. this.state = 'weakLight'
  9. }else if(this.state === 'weakLight'){
  10. console.log('强光')
  11. this.state = 'strongLight'
  12. }else{
  13. console.log('关闭')
  14. this.state = 'off'
  15. }
  16. }
  17. }

随着条件的增多、if-else会越来越多、同时也违反了开放-封闭的原则,所有的跟状态的有关的行为都封装在buttonWasPressed方法

状态机方式

  1. // 弱光类
  2. class OffLightState{
  3. constructor(light){
  4. this.light = light
  5. }
  6. bottonWasPressed(){
  7. console.log('弱光')
  8. // 设置下次执行的光亮
  9. this.light.setState(this.light.weakLightState)
  10. }
  11. }
  12. class WeakLightState{
  13. constructor(light){
  14. this.light = light
  15. }
  16. bottonWasPressed(){
  17. console.log('强光')
  18. // 设置下次执行的光亮
  19. this.light.setState(this.light.strongLightState)
  20. }
  21. }
  22. class StrongLightState{
  23. constructor(light){
  24. this.light = light
  25. }
  26. bottonWasPressed(){
  27. console.log('关灯')
  28. // 设置下次执行的光亮
  29. this.light.setState(this.light.offLightState)
  30. }
  31. }
  32. class Light{
  33. constructor(){
  34. this.offLightState = new OffLightState(this);
  35. this.weakLightState = new WeakLightState(this);
  36. this.strongLightState = new StrongLightState(this);
  37. this.button = null;
  38. this.currState = null;
  39. }
  40. init(){
  41. this.button = document.createElement('div');
  42. this.button.innerHTML = '开关按钮'
  43. this.currState = this.offLightState;
  44. document.body.appendChild(this.button)
  45. this.button.onclick = ()=>{
  46. this.currState.bottonWasPressed()
  47. }
  48. }
  49. setState( newSate ){
  50. this.currState = newSate
  51. }
  52. }
  53. let light = new Light()
  54. light.init()

总结

优点

  • 可以将不同的状态隔离、每个状态都是单独的类、减少互相依赖

    缺点

  • 状态数量比较多、状态类的数量会增加、业务场景系统变得很复杂