ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript設計パターンの状態パターンを学ぶ_JavaScriptスキル
状態モデルの鍵は、物事の内部状態を区別することです。物事の内部状態の変化は、物事の動作に変化をもたらすことがよくあります。
ライトがオンのときにスイッチを押すと、ライトはオフの状態に切り替わり、もう一度スイッチを押すとライトが再びオンになります。同じスイッチでも、状態が異なれば動作も異なります。
1. 有限状態マシン
オブジェクトの内部状態が変化したときにオブジェクトの動作を変更できるようにし、オブジェクトがそのクラスを変更したように見せます。
説明:
(1) 状態を独立したクラスにカプセル化し、リクエストを現在の状態オブジェクトに委譲します。オブジェクトの内部状態が変化すると、さまざまな動作の変化が発生します。
(2) 使用されるオブジェクトは、状態が異なるとまったく異なる動作 (委任効果) を示します
カプセル化に関しては、通常、オブジェクトの状態よりもオブジェクトの動作をカプセル化することが優先されます。
しかし、状態パターンでは、その逆になります。状態パターンの鍵は、物事の各状態を個別のクラスにカプセル化することです。
2. 例
照明プログラム (弱い光 -> 強い光 -> 消灯) サイクル
// 关灯 var OffLightState = function(light) { this.light = light; }; // 弱光 var OffLightState = function(light) { this.light = light; }; // 强光 var StrongLightState = function(light) { this.light = light; }; var Light = function(){ /* 开关状态 */ this.offLight = new OffLightState(this); this.weakLight = new WeakLightState(this); this.strongLight = new StrongLightState(this); /* 快关按钮 */ this.button = null; }; Light.prototype.init = function() { var button = document.createElement("button"), self = this; this.button = document.body.appendChild(button); this.button.innerHTML = '开关'; this.currentState = this.offLight; this.button.click = function() { self.currentState.buttonWasPressed(); } }; // 让抽象父类的抽象方法直接抛出一个异常(避免状态子类未实现buttonWasPressed方法) Light.prototype.buttonWasPressed = function() { throw new Error("父类的buttonWasPressed方法必须被重写"); }; Light.prototype.setState = function(newState) { this.currentState = newState; }; /* 关灯 */ OffLightState.prototype = new Light(); // 继承抽象类 OffLightState.prototype.buttonWasPressed = function() { console.log("关灯!"); this.light.setState(this.light.weakLight); } /* 弱光 */ WeakLightState.prototype = new Light(); WeakLightState.prototype.buttonWasPressed = function() { console.log("弱光!"); this.light.setState(this.light.strongLight); }; /* 强光 */ StrongLightState.prototype = new Light(); StrongLightState.prototype.buttonWasPressed = function() { console.log("强光!"); this.light.setState(this.light.offLight); };
追記:追加説明
OffLightState、WeakLightState、StrongLightState コンストラクターを拡張する必要があります。
new A("a"); var A = function(a) { console.log(a) } new B("b"); function B(b) { console.log(b); }
関数宣言は、通常の変数の前にホイストされます。
3. パフォーマンス最適化のポイント
(1) 状態オブジェクトの作成と破棄をどのように管理するか?
1 つ目は、状態オブジェクトが必要な場合にのみ作成され、その後破棄されます (状態オブジェクトは比較的大きいため、推奨されます)。
もう 1 つは、最初にすべての状態オブジェクトを作成し、決して破棄しないことです (状態は頻繁に変化します)。
(2) フライウェイト モードを使用して状態オブジェクトを共有します。
4. ステートマシンの JavaScript バージョン
(1) Function.prototype.call メソッド
を介して、実行のためにリクエストをリテラル オブジェクトに直接委任します。// 状态机 var FSM = { off: { buttonWasPressed: function() { console.log("关灯"); this.button.innerHTML = "下一次按我是开灯"; // 这是Light上的属性!!! this.currState = FSM.on; // 这是Light上的属性!!! } }, on: { buttonWasPressed: function() { console.log("开灯"); this.button.innerHTML = "下一次按我是关灯"; this.currState = FSM.off; } }, }; var Light = function() { this.currState = FSM.off; // 设置当前状态 this.button = null; }; Light.prototype.init = function() { var button = document.createElement("button"); self = this; button.innerHTML = "已关灯"; this.button = document.body.appendChild(button); this.button.onclick = function() { // 请求委托给FSM状态机 self.currState.buttonWasPressed.call(self); } } var light = new Light(); light.init();
(2)デリゲート関数を利用する
var delegate = function(client, delegation) { return { buttonWasPressed: function() { return delegation.buttonWasPressed.apply(client, arguments); } }; }; // 状态机 var FSM = { off: { buttonWasPressed: function() { console.log("关灯"); this.button.innerHTML = "下一次按我是开灯"; this.currState = this.onState; } }, on: { buttonWasPressed: function() { console.log("开灯"); this.button.innerHTML = "下一次按我是关灯"; this.currState = this.offState; } }, }; var Light = function() { this.offState = delegate(this, FSM.off); this.onState = delegate(this, FSM.on); this.currState = this.offState; // 设置当前状态 this.button = null; }; Light.prototype.init = function() { var button = document.createElement("button"); self = this; button.innerHTML = "已关灯"; this.button = document.body.appendChild(button); this.button.onclick = function() { // 请求委托给FSM状态机 self.currState.buttonWasPressed(); } } var light = new Light(); light.init();
この記事が、JavaScript プログラミングを学習する皆さんのお役に立てれば幸いです。