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

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

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

      深入理解JavaScript系列(43):設計模式之狀態模式

      2012-04-18 06:56  湯姆大叔  閱讀(13768)  評論(13)    收藏  舉報

      介紹

      狀態模式(State)允許一個對象在其內部狀態改變的時候改變它的行為,對象看起來似乎修改了它的類。

      正文

      舉個例子,就比如我們平時在下載東西,通常就會有好幾個狀態,比如準備狀態(ReadyState)、下載狀態(DownloadingState)、暫停狀態(DownloadPausedState)、下載完畢狀態(DownloadedState)、失敗狀態(DownloadFailedState),也就是說在每個狀態都只可以做當前狀態才可以做的事情,而不能做其它狀態能做的事兒。

      由于State模式描述了下載(Download)如何在每一種狀態下表現出不同的行為。這一模式的關鍵思想就是引入了一個叫做State的抽象類(或JS里的函數)來表示下載狀態,State函數(作為原型)為每個狀態的子類(繼承函數)聲明了一些公共接口。其每個繼承函數實現與特定狀態相關的行為,比如DownloadingState和DownloadedState分別實現了正在下載和下載完畢的行為。這些行為可以通過Download來來維護。

      讓我們來實現一把,首先定義作為其他基礎函數的原型的State函數:

      var State = function () {

      };

      State.prototype.download = function () {
      throw new Error("該方法必須被重載!");
      };

      State.prototype.pause = function () {
      throw new Error("該方法必須被重載!");
      };

      State.prototype.fail = function () {
      throw new Error("該方法必須被重載!");
      };

      State.prototype.finish = function () {
      throw new Error("該方法必須被重載!");
      };

      我們為State的原型定義了4個方法接口,分別對應著下載(download)、暫停(pause)、失敗(fail)、結束(finish)以便子函數可以重寫。

      在編寫子函數之前,我們先來編寫一個ReadyState函數,以便可以將狀態傳遞給第一個download狀態:

      var ReadyState = function (oDownload) {
      State.apply(this);
      this.oDownload = oDownload;
      };

      ReadyState.prototype = new State();

      ReadyState.prototype.download = function () {
      this.oDownload.setState(this.oDownload.getDownloadingState());
      // Ready以后,可以開始下載,所以設置了Download函數里的狀態獲取方法
      console.log("Start Download!");
      };

      ReadyState.prototype.pause = function () {
      throw new Error("還沒開始下載,不能暫停!");
      };

      ReadyState.prototype.fail = function () {
      throw new Error("文件還沒開始下載,怎么能說失敗呢!");
      };

      ReadyState.prototype.finish = function () {
      throw new Error("文件還沒開始下載,當然也不能結束了!");
      };

      該函數接收了一個Download維護函數的實例作為參數,Download函數用于控制狀態的改變和獲取(類似于中央控制器,讓外部調用),ReadyState重寫了原型的download方法,以便開始進行下載。我們繼續來看Download函數的主要功能:

      var Download = function () {
      this.oState = new ReadyState(this);
      };

      Download.prototype.setState = function (oState) {
      this.oState = oState;
      };

      // 對外暴露的四個公共方法,以便外部調用

      Download.prototype.download = function () {
      this.oState.download();
      };

      Download.prototype.pause = function () {
      this.oState.pause();
      };

      Download.prototype.fail = function () {
      this.oState.fail();
      };

      Download.prototype.finish = function () {
      this.oState.finish();
      };

      //獲取各種狀態,傳入當前this對象
      Download.prototype.getReadyState = function () {
      return new ReadyState(this);
      };

      Download.prototype.getDownloadingState = function () {
      return new DownloadingState(this);
      };

      Download.prototype.getDownloadPausedState = function () {
      return new DownloadPausedState(this);
      };

      Download.prototype.getDownloadedState = function () {
      return new DownloadedState(this);
      };

      Download.prototype.getDownloadedFailedState = function () {
      return new DownloadFailedState(this);
      };

      Download函數的原型提供了8個方法,4個是對用于下載狀態的操作行為,另外4個是用于獲取當前四個不同的狀態,這4個方法都接收this作為參數,也就是將Download實例自身作為一個參數傳遞給處理該請求的狀態對象(ReadyState 以及后面要實現的繼承函數),這使得狀態對象比必要的時候可以訪問oDownlaod。

      接下來,繼續定義4個相關狀態的函數:

      var DownloadingState = function (oDownload) {
      State.apply(this);
      this.oDownload = oDownload;
      };

      DownloadingState.prototype = new State();

      DownloadingState.prototype.download = function () {
      throw new Error("文件已經正在下載中了!");
      };

      DownloadingState.prototype.pause = function () { this.oDownload.setState(this.oDownload.getDownloadPausedState());
      console.log("暫停下載!");
      };

      DownloadingState.prototype.fail = function () { this.oDownload.setState(this.oDownload.getDownloadedFailedState());
      console.log("下載失敗!");
      };

      DownloadingState.prototype.finish = function () {
      this.oDownload.setState(this.oDownload.getDownloadedState());
      console.log("下載完畢!");
      };

      DownloadingState的主要注意事項就是已經正在下載的文件,不能再次開始下載了,其它的狀態都可以連續進行。

      var DownloadPausedState = function (oDownload) {
      State.apply(this);
      this.oDownload = oDownload;
      };

      DownloadPausedState.prototype = new State();

      DownloadPausedState.prototype.download = function () {
      this.oDownload.setState(this.oDownload.getDownloadingState());
      console.log("繼續下載!");
      };

      DownloadPausedState.prototype.pause = function () {
      throw new Error("已經暫停了,咋還要暫停呢!");
      };

      DownloadPausedState.prototype.fail = function () { this.oDownload.setState(this.oDownload.getDownloadedFailedState());
      console.log("下載失敗!");
      };

      DownloadPausedState.prototype.finish = function () {
      this.oDownload.setState(this.oDownload.getDownloadedState());
      console.log("下載完畢!");
      };

      DownloadPausedState函數里要注意的是,已經暫停的下載,不能再次暫停。

      var DownloadedState = function (oDownload) {
      State.apply(this);
      this.oDownload = oDownload;
      };

      DownloadedState.prototype = new State();

      DownloadedState.prototype.download = function () {
      this.oDownload.setState(this.oDownload.getDownloadingState());
      console.log("重新下載!");
      };

      DownloadedState.prototype.pause = function () {
      throw new Error("對下載完了,還暫停啥?");
      };

      DownloadedState.prototype.fail = function () {
      throw new Error("都下載成功了,咋會失敗呢?");
      };

      DownloadedState.prototype.finish = function () {
      throw new Error("下載成功了,不能再為成功了吧!");
      };

      DownloadedState函數,同理成功下載以后,不能再設置finish了,只能設置重新下載狀態。

      var DownloadFailedState = function (oDownload) {
      State.apply(this);
      this.oDownload = oDownload;
      };

      DownloadFailedState.prototype = new State();

      DownloadFailedState.prototype.download = function () {
      this.oDownload.setState(this.oDownload.getDownloadingState());
      console.log("嘗試重新下載!");
      };

      DownloadFailedState.prototype.pause = function () {
      throw new Error("失敗的下載,也不能暫停!");
      };

      DownloadFailedState.prototype.fail = function () {
      throw new Error("都失敗了,咋還失敗呢!");
      };

      DownloadFailedState.prototype.finish = function () {
      throw new Error("失敗的下載,肯定也不會成功!");
      };同理,DownloadFailedState函數的失敗狀態,也不能再次失敗,但可以和finished以后再次嘗試重新下載。

      調用測試代碼,就非常簡單了,我們在HTML里演示吧,首先是要了jquery,然后有3個按鈕分別代表:開始下載、暫停、重新下載。(注意在Firefox里用firebug查看結果,因為用了 console.log方法)。

      <html>
      <head>
      <link type="text/css" rel="stylesheet" href="http://www.rzrgm.cn/css/style.css" />
      <title>State Pattern</title>
      <script type="text/javascript" src="/jquery.js"></script>
      <script type="text/javascript" src="Download.js"></script>
      <script type="text/javascript" src="states/State.js"></script>
      <script type="text/javascript" src="states/DownloadFailedState.js"></script>
      <script type="text/javascript" src="states/DownloadPausedState.js"></script>
      <script type="text/javascript" src="states/DownloadedState.js"></script>
      <script type="text/javascript" src="states/DownloadingState.js"></script>
      <script type="text/javascript" src="states/ReadyState.js"></script>
      </head>
      <body>
      <input type="button" value="開始下載" id="download_button" />
      <input type="button" value="暫停" id="pause_button" />
      <input type="button" value="重新下載" id="resume_button" />
      <script type="text/javascript">
      var oDownload = new Download();
      $(
      "#download_button").click(function () {
      oDownload.download();
      });

      $(
      "#pause_button").click(function () {
      oDownload.pause();
      });

      $(
      "#resume_button").click(function () {
      oDownload.download();
      });
      </script>
      </body>
      </html>

      總結

      狀態模式的使用場景也特別明確,有如下兩點:

      1. 一個對象的行為取決于它的狀態,并且它必須在運行時刻根據狀態改變它的行為。
      2. 一個操作中含有大量的分支語句,而且這些分支語句依賴于該對象的狀態。狀態通常為一個或多個枚舉常量的表示。

      參考:https://github.com/tcorral/Design-Patterns-in-Javascript/blob/master/State/1/index.html

      同步與推薦

      本文已同步至目錄索引:深入理解JavaScript系列

      深入理解JavaScript系列文章,包括了原創,翻譯,轉載等各類型的文章,如果對你有用,請推薦支持一把,給大叔寫作的動力。

      主站蜘蛛池模板: 啊┅┅快┅┅用力啊岳网站| AV最新高清无码专区| 久久亚洲精品中文字幕馆| 日韩人妻少妇一区二区三区| 少妇又爽又刺激视频| 久久99精品国产麻豆宅宅| 中文午夜乱理片无码| 成全世界免费高清观看| 亚洲伊人久久大香线蕉| 久久精品国产99久久久古代| 哈巴河县| 色综合天天综合网国产人| 三级三级三级A级全黄| 国内精品久久久久久无码不卡 | 亚洲精品天堂在线观看| 精品国产中文字幕在线| 精品国产日韩亚洲一区| 国产午夜福利视频在线| av在线播放观看国产| 国产精品理论片| 国产精品白丝一区二区三区| A级日本乱理伦片免费入口| 亚洲人妻精品中文字幕| 国产区成人精品视频| 少妇人妻偷人精品视蜜桃| 国产日韩综合av在线| 免费观看全黄做爰大片| 久热伊人精品国产中文| 欧美成人精品三级在线观看| 熟女一区| 国产综合久久亚洲综合| 亚洲av无码乱码在线观看野外| 97国产成人无码精品久久久| 亚洲 卡通 欧美 制服 中文 | 国产乱人伦AV在线麻豆A| 日韩精品区一区二区三vr| 成人精品自拍视频免费看| 亚洲国产精品一区二区第一页| 国产偷自视频区视频| 在线免费播放av观看| 中文字幕人成无码免费视频 |