JavaScript状态模式及适配器模式使用讲解
volit_ 人气:0一、状态模式
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类
1.基本实现
//下面以一个开灯程序演示状态模式 //灯共用三种状态,分别是‘关闭',‘弱光‘和'强光‘。每次按下开关按钮都会换挡。 let OfflightState = function (light) { this.light = light; } OfflightState.prototype.buttonPressed = function () { console.light('弱光'); this.light.setState(this.light.weakLightState); } let WeakLightState = function (light) { this.light = light; } WeakLightState.prototype.buttonPressed = function () { console.log('强光') this.light.setState(this.light.strongLightState); } let StrongLightState = function (light) { this.light = light; } StrongLightState.prototype.buttonPressed = function () { console.log('关闭'); this.light.setState(this.light.offlightState) } let Light = function () { this.offlightState = new OfflightState(this); this.weakLightState = new WeakLightState(this); this.strongLightState = new StrongLightState(this); this.button = null; } Light.prototype.init = function () { let button = document.createElement('button'); self = this; this.button = document.body.appendChild(button); this.button.innerHTML = '开关'; this.button.currState = this.offlightState; this.button.onclick = function () { self.currState.buttonPressed; } } Light.prototype.setState = function (newState) { this.currState = newState; } let light = new Light(); light.init();
以上代码实现了一个基本的状态模式,状态的切换规律事先被定义好在各个状态类中,主体上无需关心切换的细节。如果日后又新增了一个状态,那我们只要编写好新的状态类,加入到原有代码中就可以了。
2.状态模式的优缺点
(1)状态模式定义了状态与行为之间的关系,并将它们封装在一个类里。通过增加新的状态类,很容易增加新的状态和转换
(2)避免Context无限膨胀,状态切换的逻辑被分布在状态类中,也去掉了Context中原本过多的分支。
(3)用对象代替字符串来记录当前状态,使得状态的切换更加一目了然。
(4)Context中的请求动作和状态类中封装的行为可以非常容易地独立变化而互不影响。
3.状态模式中的性能优化点
(1)状态可以等待需要的时候再创建,也可以一开始就创建好,具体依据实际场景、
(2)state对象可以在多个类之间共享。
二、适配器模式
解决两个软件实体间接口不兼容问题
适配器模式的应用
let googleMap = { show: function () { console.log('开始渲染谷歌地图'); } } let baiduMap = { show: function () { console.log('开始渲染百度地图'); } } let renderMap = function (map) { map.show(); } /** * 以上代码段实现了渲染不同地图的功能。现在假设BaiduMap的api改成了display,修改源代码势必不太符合开闭原则,这时候我们可以通过新建一个适配器来达到目的 */ let baiduMapAdapter = { show: function () { return baiduMap.display(); } } renderMap(baiduMapAdapter);
加载全部内容