状态和行为:
所谓对象的状态,通常指的就是对象实例的属性的值;而行为指的就是对象的功能,再具体点说,行为大多可以对应到方法上。
状态模式的功能就是分离状态的行为,通过维护状态的变化,来调用不同状态对应的不同功能。也就是说,状态和行为是相关联的,它们的关系可以描述为:状态决定行为。
由于状态是在运行期被改变的,因此行为也会在运行期根据状态的改变而改变。
环境和状态处理对象:
在状态模式中,环境(Context)是持有状态的对象,但是环境(Context)自身并不处理跟状态相关的行为,而是把处理状态的功能委托给了状态对应的状态处理类来处理。
在具体的状态处理类中经常需要获取环境(Context)自身的数据,甚至在必要的时候会回调环境(Context)的方法,因此,通常将环境(Context)自身当作一个参数传递给具体的状态处理类。
看一个具体的实例:
1.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("该方法必须被重载!"); };
2.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(); };
3.6种不同的状态(每种状态都会调用Download类的改变状态的方法,进行状态切换)
(1)准备状态:
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("文件还没开始下载,当然也不能结束了!"); };
(2)
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("下载完毕!"); };
(3)
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("下载完毕!"); };
(4)
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("下载成功了,不能再为成功了吧!"); };
(5)
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("失败的下载,肯定也不会成功!"); };
4.首页:
<body> <input type="button" value="开始下载" id="download_button" /> <input type="button" value="暂停" id="pause_button" /> <input type="button" value="重新下载" id="resume_button" /> <script> var oDownload = new Download(); $("#download_button").click(function () { oDownload.download(); }); $("#pause_button").click(function () { oDownload.pause(); }); $("#resume_button").click(function () { oDownload.download(); }); </script> </body>