Modèle de conception JavaScript de chaîne de responsabilité

Aujourd’hui, nous allons parler du modèle de chaîne de responsabilité.

Ce modèle dissocie l’expéditeur et le destinataire des demandes. Cela se fait avec une chaîne d’objets qui peuvent gérer la demande elle-même ou la transmettre à l’objet suivant. Confus? Continuer à lire. Structure de la chaîne de responsabilité Trois parties composent le modèle de la chaîne de responsabilité: l’expéditeur, le destinataire et la demande. L’expéditeur fait des demandes. Le récepteur est une chaîne d’un ou plusieurs objets qui choisissent de traiter la demande ou de la transmettre. La requête elle-même peut être un objet qui encapsule toutes les données appropriées, ou il peut simplement s’agir d’un appel de fonction normal sur le récepteur sans arguments. Les expéditeurs envoient la demande au premier objet récepteur de la chaîne. L’expéditeur ne connaît que cette première partie de la chaîne et rien des autres destinataires. Le premier récepteur gère la demande ou la transmet au prochain récepteur de la chaîne. Chaque récepteur ne connaît que le récepteur suivant sur la ligne. La demande continuera sur la ligne jusqu’à ce que la demande soit traitée ou qu’il n’y ait plus de destinataires auxquels la transmettre, à quel point une erreur est générée ou que rien ne se passe, selon la façon dont vous concevez votre chaîne. Exemple de chaîne de responsabilité Pour notre exemple, nous allons créer un guichet automatique. La chaîne sera composée de billets d’un dollar de différentes tailles. Lorsque vous demandez de l’argent, la machine commence avec les plus grosses factures et tire autant de celles dont elle a besoin, puis passe à la prochaine plus petite facture et ainsi de suite jusqu’à ce que nous ayons tout l’argent ou que nous soyons à court de factures. Cet exemple est volontairement simple, car il permet de montrer le concept plus clairement sans diluer le code avec trop d’implémentations spécifiques à l’exemple. Nous allons commencer par créer la ‘classe’ du récepteur: MoneyStacks. Normalement, ce serait juste une interface qui serait implémentée par différents récepteurs, mais cet exemple est suffisamment simple pour que la seule variation entre chacun des récepteurs soit la taille des factures dans la pile. Nous allons simplement définir ce nombre via un paramètre dans le constructor.var MoneyStack = function (billSize) {this.billSize = billSize; this.next = null;} MoneyStack.prototype = {retrait: fonction (montant) {var numOfBills = Math.floor (montant / this.billSize); if (numOfBills> 0) {// Éjecte les factureshis._ejectMoney (numOfBill); // Réduisez le montant en fonction de la somme d’argent que nous éjectons quantité = montant – (this.billSize * numOfBills);} // S’il reste de l’argent à retirer et si nous avons // une autre pile sur la ligne, passez la requête à ammount> 0 && this.next && this.next. remove (amount);}, // définit la pile suivante sur la chaîne etNextStack: function (stack) {this.next = stack;}, // méthode privée qui éjecte le money_ejectMoney (numOfBills) {console.log (numOfBills +  » $ « + this.billSize + » facture (s) a / ont été crachée (s) « );}} Le calcul derrière cela est assez simple. La fonction de retrait est ce que la capacité de chaînage utilise en éjectant les factures requises, puis en transmettant la demande au suivant de la chaîne, le cas échéant. Construisons maintenant le guichet automatique. Son constructeur instancie toutes les piles d’argent et les place dans leur ordre hiérarchique. Quand quelqu’un appelle la méthode de retrait, la responsabilité de retirer est transférée à la chaîne de piles d’argent var ATM = function () {// Créer les piles d’argent // Nous allons vous montrer l’implémentation de ceci ci-dessous var stack100 = new MoneyStack (100 ), stack50 = new MoneyStack (50), stack20 = new MoneyStack (20), stack10 = new MoneyStack (10), stack5 = new MoneyStack (5), stack1 = new MoneyStack (1); // Définit la hiérarchie des piles stack100.setNextStack (stack50); stack50.setNextStack (stack20); stack20.setNextStack (stack10); stack10.setNextStack (stack5); stack5.setNextStack (pile1); // Définit la pile supérieure comme propriététhis.moneyStacks = stack100; } ATM.prototype.withdraw = function (montant) {this.moneyStacks.withdraw (montant);} // USOvar atm = new ATM (); Retirer atm (186); / * sorties: 1 billet (s) 100 $ 1 billet (s) 50 $ cracher 1 billet (s) 20 $ cracher 1 billet (s) 10 $ cracher 1 billet (s) 5 $ cracher 1 billet (s) 1 $ ) a été craché * / Retrait atm (72); / * sorties: 1 billet (s) de 50 $ a été craché 1 billet (s) de 20 $ a été craché 2 billets de 1 $ ont été crachés * / Fin de mes responsabilités C’est tout ce qu’il y a à ce modèle. C’est assez simple. Comme les modèles Command et Observer, son but est de découpler l’expéditeur des récepteurs, mais pour des raisons différentes et avec des décalages différents. En raison de sa structure hiérarchique, il est également similaire au motif composite et peut même être injecté dans le motif composite pour un vrai plaisir.