<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Javascript設計模式之我見:狀態模式

      大家好!本文介紹狀態模式及其在Javascript中的應用。

      模式介紹

      定義

      當一個對象的內在狀態改變時允許改變其行為,這個對象看起來像是改變了其類。

      狀態模式主要解決的是控制一個對象狀態的條件表達式過于復雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類中,可以把復雜的判斷邏輯簡化。

      類圖及說明

      State:抽象狀態

      接口或抽象類,負責對象狀態定義,并且封裝環境角色以實現狀態切換

      ConcreState:具體狀態

      每一個具體狀態必須完成兩個職責:本狀態的行為管理以及趨向狀態處理。通俗地說,就是本狀態下要做的事情,以及本狀態如何過渡到其他狀態。

      Context:環境 

      定義客戶端需要的接口,并且負責具體狀態的切換。

      應用場景

      • 一個對象的行為取決于它的狀態, 并且它必須在運行時刻根據狀態改變它的行為。
      • 代碼中包含大量與對象狀態有關的條件語句:一個操作中含有龐大的多分支的條件(if else(或switch case)語句,且這些分支依賴于該對象的狀態。這個狀態通常用一個或多個枚舉常量表示。通常 , 有多個操作包含這一相同的條件結構。 State模式將每一個條件分支放入一個獨立的類中。這使得你可以根據對象自身的情況將對象的狀態作為一個對象,這一對象可以不依賴于其他對象而獨立變化。

      優點

      1. 避免了過多的 swith…case 或者 if..else 語句的使用,避免了程序的復雜性
      2. 很好的使用體現了開閉原則和單一職責原則,每個狀態都是一個子類,你要增加狀態就增加子類,你要修改狀態,你只修改一個子類就可以了
      3. 封裝性非常好,這也是狀態模式的基本要求。狀態變換放置到了類的內部來實現,外部的調用不用知道類內部如何實現狀態和行為的變換。

      缺點 

      1. 具體狀態類可能會有很多個,不好管理。

      狀態模式在Javascript中的應用

      我的理解

      • ConcreteState具體狀態類有兩個職責:處理本狀態必須完成的任務;過渡到其他狀態。
      • 可以采自下而上的方法來實現狀態類,即先實現ConcreteState類,然后再將ConcreteState類的共性提取出來,形成父類State。

      類圖及說明

      User:使用者

      使用者具有不同的狀態,它創建Context類并將狀態的邏輯委托給Context類處理。

      示例

      小時候大家應該都玩過魂斗羅游戲吧,魂斗羅吃了無敵道具后會變成刀槍不入,吃了火力增強道具后會變成殺人機器。讓我們來看看它的狀態是如何轉換的。

      狀態圖

      魂斗羅Warrior有NORMAL、INVINCIBLE、POWER、DEAD四個狀態,每個狀態都有beNormal、beInvincible、bePower、dead四個方法。有timeOver、getInvincible、getPower、beShotDead四個觸發狀態的事件。

      類圖

       

      代碼

      代碼中使用的庫:YOOP

      Warrior

          var Warrior = YYC.Class({
              Private: {
                  _state: null
              },
              Public: {
                  //*事件標志
      
                  _getInvincible: false,
                  _getPower: false,
                  _timeOver: false,
                  _beShotDead: false,
      
                  setState: function (state) {
                      this._state = state;
                  },
                  //*狀態方法
      
                  beNormal: function () {
                      switch (this._state) {
                          case  Warrior.NORMAL_STATE:
                              //本狀態beNormal方法的邏輯。已經處于NORMAL狀態,不用再轉換為NORMAL狀態了
                              console.log("恢復正常");
                              break;
                          case Warrior.INVINCIBLE_STATE:
                              //INVINCIBLE狀態下beNormal方法的邏輯
                              console.log("恢復正常");
                              //從INVINCIBLE狀態轉換到NORMAL狀態
                              this.setState(Warrior.NORMAL_STATE);
                              break;
                          case Warrior.POWER_STATE:
                              //POWER狀態下beNormal方法的邏輯
                              console.log("恢復正常");
                              //從POWER狀態轉換到NORMAL狀態
                              this.setState(Warrior.NORMAL_STATE);
                              break;
                          case Warrior.DEAD_STATE:
                              //不能起死回生
                              break;
                      }
                  },
                  beInvincible: function () {
                      switch (this._state) {
                          case  Warrior.NORMAL_STATE:
                              console.log("無敵");
                              this.setState(Warrior.INVINCIBLE_STATE);
                              break;
                          case Warrior.INVINCIBLE_STATE:
                              console.log("無敵");
                              break;
                          case Warrior.POWER_STATE:
                              console.log("無敵");
                              this.setState(Warrior.INVINCIBLE_STATE);
                              break;
                          case Warrior.DEAD_STATE:
                              break;
                      }
                  },
                  bePower: function () {
                      switch (this._state) {
                          case  Warrior.NORMAL_STATE:
                              console.log("火力增強");
                              this.setState(Warrior.POWER_STATE);
                              break;
                          case Warrior.INVINCIBLE_STATE:
                              console.log("火力增強");
                              this.setState(Warrior.POWER_STATE);
                              break;
                          case Warrior.POWER_STATE:
                              console.log("火力增強");
                              break;
                          case Warrior.DEAD_STATE:
                              break;
                      }
                  },
                  dead: function () {
                      switch (this._state) {
                          case  Warrior.NORMAL_STATE:
                              console.log("死亡");
                              this.setState(Warrior.DEAD_STATE);
                              break;
                          case Warrior.INVINCIBLE_STATE:
                              //都無敵了當然不會死亡
                              break;
                          case Warrior.POWER_STATE:
                              console.log("死亡");
                              this.setState(Warrior.DEAD_STATE);
                              break;
                          case Warrior.DEAD_STATE:
                              console.log("死亡");
                              break;
                      }
                  },
      
                  action: function () {
                      //*此處進行觸發狀態的事件判斷
      
                      if (this._timeOver) {
                          this.beNormal();
                      }
                      else if (this._getInvincible) {
                          this.beInvincible();
                      }
                      else if (this._getPower) {
                          this.bePower();
                      }
                      else if (this._beShotDead) {
                          this.dead();
                      }
                  }
              },
              Static: {
                  NORMAL_STATE: 1,
                  INVINCIBLE_STATE: 2,
                  POWER_STATE: 3,
                  DEAD_STATE: 4
              }
          });

      場景類

          function _resetFlag(warrior) {
              warrior._getInvincible = false;
              warrior._getPower = false;
              warrior._timeOver = false;
              warrior._beShotDead = false;
          }
          function _getInvincible(warrior) {
              _resetFlag(warrior);
      
              warrior._getInvincible = true;
          }
          function _getPower(warrior) {
              _resetFlag(warrior);
      
              warrior._getPower = true;
          }
          function _beShotDead(warrior) {
              _resetFlag(warrior);
      
              warrior._beShotDead = true;
          }
      
      
          function main() {
              var warrior = new Warrior();
      
              //初始狀態為Normal
              warrior.setState(Warrior.NORMAL);
      
              //獲得無敵道具,進入無敵狀態
              _getInvincible(warrior);
      
              warrior.action();
      
              //獲得火力增強道具,進入火力增強狀態
              _getPower(warrior);
      
              warrior.action();
      
              //被擊中,進入死亡狀態
              _beShotDead(warrior);
      
              warrior.action();
          }

      運行結果

      示例分析

      我們來看看這段程序的問題。

      • 實現類Warrior用了大量的switch...case判斷,增加了大量代碼,可讀性和可維護性差。
      • 擴展性差。
        如果要增加1個狀態,則beNormal、beInvincible、bePower、dead方法中都要增加判斷條件,這不符合開閉原則。

      使用狀態模式

      類圖

      代碼

      State

      var State = YYC.AClass({
          Public: {
              setContext: function (context) {
                  this.P_context = context;
              }
          },
          Protected: {
              P_context: null
          },
          Abstract: {
              beNormal: function () {
              },
              beInvincible: function () {
              },
              bePower: function () {
              },
              dead: function () {
              }
          }
      });

      NormalState

      var NormalState = YYC.Class(State, {
          Public: {
              //*在具體狀態類中進行觸發狀態的事件判斷
      
              beNormal: function () {
                  if (this.P_context.warrior.timeOver) {
                      //本狀態邏輯
                      console.log("恢復正常");
                  }
              },
              beInvincible: function () {
                  if (this.P_context.warrior.getInvincible) {
                      //過度到無敵狀態的邏輯
                      this.P_context.setState(Context.InvincibleState);
                      this.P_context.beInvincible();
                  }
              },
              bePower: function () {
                  if (this.P_context.warrior.getPower) {
                      //過度到火力增強狀態的邏輯
                      this.P_context.setState(Context.PowerState);
                      this.P_context.bePower();
                  }
              },
              dead: function () {
                  if (this.P_context.warrior.beShotDead) {
                      //過度到死亡狀態的邏輯
                      this.P_context.setState(Context.DeadState);
                      this.P_context.dead();
                  }
              }
          }
      });

      InvincibleState

      var InvincibleState = YYC.Class(State, {
          Public: {
              beNormal: function () {
                  if (this.P_context.warrior.timeOver) {
                      this.P_context.setState(Context.NormalState);
                      this.P_context.beNormal();
                  }
              },
              beInvincible: function () {
                  if (this.P_context.warrior.getInvincible) {
                      console.log("無敵");
                  }
              },
              bePower: function () {
                  if (this.P_context.warrior.getPower) {
                      this.P_context.setState(Context.PowerState);
                      this.P_context.bePower();
                  }
              },
              dead: function () {
                  //都無敵了當然不會死亡
              }
          }
      });

      PowerState

      var PowerState = YYC.Class(State, {
          Public: {
              beNormal: function () {
                  if (this.P_context.warrior.timeOver) {
                      this.P_context.setState(Context.NormalState);
                      this.P_context.beNormal();
                  }
              },
              beInvincible: function () {
                  if (this.P_context.warrior.getInvincible) {
                      this.P_context.setState(Context.InvincibleState);
                      this.P_context.beInvincible();
                  }
              },
              bePower: function () {
                  if (this.P_context.warrior.getPower) {
                      console.log("火力增強");
                  }
              },
              dead: function () {
                  if (this.P_context.warrior.beShotDead) {
                      this.P_context.setState(Context.DeadState);
                      this.P_context.dead();
                  }
              }
          }
      });

      DeadState

      var DeadState = YYC.Class(State, {
          Public: {
              beNormal: function () {
                  //不能起死回生
              },
              beInvincible: function () {
                  //掛都掛了,還怎么無敵
              },
              bePower: function () {
                  //掛都掛了,還怎么火力增強
              },
              dead: function () {
                  if (this.P_context.warrior.beShotDead) {
                      console.log("死亡");
                  }
              }
          }
      });

      Context

      var Context = YYC.Class({
          Init: function (warrior) {
              this.warrior = warrior;
          },
          Private: {
              _state: null
          },
          Public: {
              warrior: null,
      
              setState: function (state) {
                  this._state = state;
                  //把當前的上下文通知到當前狀態類對象中
                  this._state.setContext(this);
              },
              beNormal: function () {
                  this._state.beNormal();
              },
              beInvincible: function () {
                  this._state.beInvincible();
              },
              bePower: function () {
                  this._state.bePower();
              },
              dead: function () {
                  this._state.dead();
              }
          },
          Static: {
              NormalState: new NormalState(),
              InvincibleState: new InvincibleState(),
              PowerState: new PowerState(),
              DeadState: new DeadState()
          }
      });

      Warrior

      var Warrior = YYC.Class({
          Init: function () {
              this._context = new Context(this);
              //設置初始狀態
              this._context.setState(Context.NormalState);
          },
          Private: {
              _context: null
          },
          Public: {
              //*事件標志
      
              getInvincible: false,
              getPower: false,
              timeOver: false,
              beShotDead: false,
      
              action: function () {
                  this._context.beNormal();
                  this._context.beInvincible();
                  this._context.bePower();
                  this._context.dead();
              }
          }
      });

      場景類Client

      function _resetFlag(warrior) {
          warrior.getInvincible = false;
          warrior.getPower = false;
          warrior.imeOver = false;
          warrior.beShotDead = false;
      }
      function _getInvincible(warrior) {
          _resetFlag(warrior);
      
          warrior.getInvincible = true;
      }
      function _getPower(warrior) {
          _resetFlag(warrior);
      
          warrior.getPower = true;
      }
      function _beShotDead(warrior) {
          _resetFlag(warrior);
      
          warrior.beShotDead = true;
      }
      
      
      function main() {
          var warrior = new Warrior();
      
          //獲得無敵道具,進入無敵狀態
          _getInvincible(warrior);
      
          warrior.action();
      
          //獲得火力增強道具,進入火力增強狀態
          _getPower(warrior);
      
          warrior.action();
      
          //被擊中,進入死亡狀態
          _beShotDead(warrior);
      
          warrior.action();
      }

      運行結果

      示例分析

        將觸發狀態的事件判斷移到Warrior類中

      目前是在具體狀態類中進行觸發狀態的事件判斷,這樣造成了重復判斷??梢詫⑴袛嗵岢鰜?,放到Warrior類的action中進行判斷:

      Warrior

              action: function () {
                  if (this.timeOver) {
                      this._context.beNormal();
                  }
                  else if (this.getInvincible) {
                      this._context.beInvincible();
                  }
                  else if (this.getPower) {
                      this._context.bePower();
                  }
                  else if (this.beShotDead) {
                      this._context.dead();
                  }
              }

      NormalState(其它三個具體狀態類做相同的重構)

      var NormalState = YYC.Class(State, {
          Public: {
              beNormal: function () {
                  //本狀態邏輯
                  console.log("恢復正常");
              },
              beInvincible: function () {
                  //過度到無敵狀態的邏輯
                  this.P_context.setState(Context.InvincibleState);
                  this.P_context.beInvincible();
              },
              bePower: function () {
                  //過度到火力增強狀態的邏輯
                  this.P_context.setState(Context.PowerState);
                  this.P_context.bePower();
              },
              dead: function () {
                  //過度到死亡狀態的邏輯
                  this.P_context.setState(Context.DeadState);
                  this.P_context.dead();
              }
          }
      });

          局限性

      如果不同狀態轉換為同一狀態的觸發事件不同,那么就不能把觸發狀態的事件移到Warrior類中,而需要在具體狀態類中判斷。

      例如,現在從NORMAL狀態轉換到POWER狀態的觸發事件為“獲得火力增強道具”,而從INVINCIBLE狀態轉換到POWER狀態的觸發事件為“持續時間結束且獲得火力增強道具”:

      那么就不能在Warrior中進行統一的事件判斷了,而應該在具體狀態類NormalState、InvincibleState類中判斷:

      NormalState

              bePower: function () {
                  if (this.P_context.warrior.getPower) {
                      this.P_context.setState(Context.PowerState);
                      this.P_context.bePower();
                  }
              },

      InvincibleState

              bePower: function () {
                  if (this.P_context.warrior.timeOver && this.P_context.warrior.getPower) {
                      this.P_context.setState(Context.PowerState);
                      this.P_context.bePower();
                  }
              },

          結論

      不同狀態轉換為同一狀態的觸發事件相同,則可以將觸發狀態的事件判斷放到調用Context的類中;否則將觸發狀態的事件判斷放到具體狀態類中。

      參考資料

      《設計模式之禪》

      <<Head First設計模式>>之狀態模式學習篇

      posted @ 2013-10-13 19:31  楊元超  閱讀(1354)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 国产一区二区三区小说| 免费无码黄网站在线观看| 欧美私人情侣网站| 无码国产偷倩在线播放| 邻水| 亚洲色av天天天天天天| 亚洲色大成网站WWW永久麻豆| 亚洲乱码国产乱码精品精| 国产精品女同一区三区五区| 国产第一页浮力影院入口| 久久久亚洲欧洲日产国码αv| 桃花岛亚洲成在人线AV| 日本不卡码一区二区三区| 亚洲日本va午夜在线影院| 少妇大叫太大太爽受不了| 亚洲国产精品va在线观看麻豆| 国产学生裸体无遮挡免费| 久久综合色之久久综合色| 无码人妻出轨黑人中文字幕| 亚洲国产成人综合精品| 激情伊人五月天久久综合| 日本黄页网站免费观看| 成人久久精品国产亚洲av| 国产午夜精品亚洲精品国产| 国产69精品久久久久777| 久久综合狠狠综合久久激情| 国产精品普通话国语对白露脸| 麻豆精品久久久久久久99蜜桃| 91福利一区福利二区| 九九热免费精品视频在线| 欧美日韩性高爱潮视频| 永久免费精品性爱网站| 国产高清一区二区不卡| 国产激情一区二区三区午夜| 东北妇女精品bbwbbw| 人妻少妇一区二区三区| 亚洲www永久成人网站| 在线a亚洲老鸭窝天堂| 亚洲男人天堂一级黄色片| 午夜毛片不卡免费观看视频| 伊人久久大香线蕉综合网站|