Maison  >  Article  >  interface Web  >  Apprenez le modèle d'état des modèles de conception JavaScript_compétences Javascript

Apprenez le modèle d'état des modèles de conception JavaScript_compétences Javascript

WBOY
WBOYoriginal
2016-05-16 15:20:491169parcourir

La clé du modèle d'État est de distinguer l'état interne des choses. Les changements dans l'état interne des choses conduisent souvent à des changements dans le comportement des choses.

Lorsque la lumière est allumée et que vous appuyez sur l'interrupteur, la lumière s'éteint ; appuyez à nouveau sur l'interrupteur et la lumière se rallume. Le même commutateur se comporte différemment selon les états.

1. Machine à états finis

  • Le nombre total d'états (état) est limité.
  • A tout moment, vous n'êtes que dans un seul état.
  • Sous certaines conditions, il y aura une transition d'un état à un autre.

Permet à un objet de changer de comportement lorsque son état interne change, donnant l'impression que l'objet modifie sa classe.
Explication :
(1) Encapsulez l'état dans une classe indépendante et déléguez la demande à l'objet d'état actuel. Lorsque l'état interne de l'objet change, différents changements de comportement se produiront.
(2) Les objets utilisés ont des comportements complètement différents (effet de délégation) selon les états

En matière d'encapsulation, la priorité est généralement donnée à encapsuler le comportement de l'objet plutôt que l'état de l'objet.
Mais dans le modèle d’état, c’est tout le contraire. La clé du modèle d’état est d’encapsuler chaque état de choses dans une classe distincte.

2. Exemple

Cycle du programme d'éclairage (lumière faible –> lumière forte –> lumière éteinte)

// 关灯
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);
};

PS : Explication supplémentaire
Les constructeurs OffLightState, WeakLightState, StrongLightState doivent être avancés.

new A("a");
var A = function(a) {
  console.log(a)
}

new B("b");
function B(b) {
  console.log(b);
}

Les déclarations de fonctions seront hissées avant les variables ordinaires.

3. Points d'optimisation des performances

(1) Comment gérer la création et la destruction des objets d'État ?
Le premier n'est créé que lorsque l'objet d'état est nécessaire puis détruit (l'objet d'état est relativement volumineux, de préférence),
L'autre consiste à créer tous les objets d'état au début et à ne jamais les détruire (l'état change fréquemment).
(2) Utilisez le mode poids mouche pour partager un objet d'état.

4. Version JavaScript de la machine à états

(1) Déléguer directement la requête à un objet littéral pour exécution via la méthode 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) Utiliser la fonction délégué

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();

J'espère que cet article sera utile à tous ceux qui apprennent la programmation JavaScript.

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn