modèle de chaîne de responsabilité


Comme son nom l'indique, le modèle de chaîne de responsabilité crée une chaîne d'objets récepteurs pour les requêtes. Ce modèle dissocie l'expéditeur et le destinataire de la demande en fonction du type de demande. Ce type de modèle de conception est un modèle comportemental.


Dans ce modèle, chaque récepteur contient généralement une référence à un autre récepteur. Si un objet ne peut pas gérer la requête, il transmet alors la même requête au destinataire suivant, et ainsi de suite.

Introduction

Intention : Éviter le couplage des expéditeurs et des récepteurs de requêtes, permettre à plusieurs objets de recevoir des requêtes et connecter ces objets dans une chaîne, et le La requête est transmise le long de cette chaîne jusqu'à ce qu'un objet la gère.

Solution principale : Le processeur de la chaîne de responsabilité est responsable du traitement de la demande. Le client n'a qu'à envoyer la demande à la chaîne de responsabilité et n'a pas besoin de se soucier du traitement de la demande. détails et livraison de la demande, donc la chaîne de responsabilité dissocie l'expéditeur de la demande du gestionnaire de la demande.

Quand utiliser : Pour filtrer de nombreux canaux lors du traitement des messages.

Comment résoudre : Toutes les classes interceptées implémentent des interfaces unifiées.

Code clé : Le gestionnaire s'agrège dans HanleRequest pour déterminer s'il convient. Si les conditions ne sont pas remplies, il sera transmis et défini avant de le transmettre à qui.

Exemples d'application : 1. "Tambours et fleurs qui passent" dans Dream of Red Mansions. 2. Événement bouillonnant dans JS. 3. Le traitement de l'Encodage par Apache Tomcat dans JAVA WEB, l'intercepteur de Struts2, et le Filtre de la servlet jsp.

Avantages : 1. Réduire l'accouplement. Il découple l’expéditeur et le destinataire de la demande. 2. Objets simplifiés. L'objet n'a pas besoin de connaître la structure de la chaîne. 3. Améliorez la flexibilité d’attribution de responsabilités aux objets. Permet l'ajout ou la suppression dynamique de responsabilités en changeant les membres au sein de la chaîne ou en déplaçant leur ordre. 4. Il est très pratique d’ajouter de nouvelles classes de traitement des requêtes.

Inconvénients : 1. Il n'y a aucune garantie que la demande sera reçue. 2. Les performances du système seront affectées dans une certaine mesure et il n'est pas pratique de déboguer le code, ce qui peut provoquer des appels en boucle. 3. Il peut être difficile d'observer les caractéristiques d'exécution, ce qui entrave le débogage.

Scénarios d'utilisation : 1. Plusieurs objets peuvent gérer la même requête. L'objet spécifique qui gère la requête est automatiquement déterminé au moment de l'exécution. 2. Soumettez une demande à l'un des multiples objets sans spécifier explicitement le destinataire. 3. Un groupe d'objets peut être désigné dynamiquement pour gérer les demandes.

Remarque : J'ai rencontré de nombreuses applications dans JAVA WEB.

Implémentation

Nous créons une classe abstraite AbstractLogger, avec un niveau de journalisation détaillé. Nous créons ensuite trois types de loggers, tous étendant AbstractLogger. Si le niveau de chaque message de l'enregistreur appartient à son propre niveau, si tel est le cas, il sera imprimé en conséquence, sinon il ne sera pas imprimé et le message sera transmis au prochain enregistreur.

chain_pattern_uml_diagram.jpg

Étape 1

Créez une classe d'enregistreur abstraite.

AbstractLogger.java

public abstract class AbstractLogger {
   public static int INFO = 1;
   public static int DEBUG = 2;
   public static int ERROR = 3;

   protected int level;

   //责任链中的下一个元素
   protected AbstractLogger nextLogger;

   public void setNextLogger(AbstractLogger nextLogger){
      this.nextLogger = nextLogger;
   }

   public void logMessage(int level, String message){
      if(this.level <= level){
         write(message);
      }
      if(nextLogger !=null){
         nextLogger.logMessage(level, message);
      }
   }

   abstract protected void write(String message);
	
}

Étape 2

Créez une classe d'entité qui étend cette classe d'enregistreur.

ConsoleLogger.java

public class ConsoleLogger extends AbstractLogger {

   public ConsoleLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {		
      System.out.println("Standard Console::Logger: " + message);
   }
}

ErrorLogger.java

public class ErrorLogger extends AbstractLogger {

   public ErrorLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {		
      System.out.println("Error Console::Logger: " + message);
   }
}

FileLogger.java

public class FileLogger extends AbstractLogger {

   public FileLogger(int level){
      this.level = level;
   }

   @Override
   protected void write(String message) {		
      System.out.println("File::Logger: " + message);
   }
}

Étape 3

Créez différents types d'enregistreurs. Donnez-leur différents niveaux d'erreur et dans chaque enregistreur, définissez l'enregistreur suivant. L'enregistreur suivant dans chaque enregistreur représente une partie de la chaîne.

ChainPatternDemo.java

public class ChainPatternDemo {
	
   private static AbstractLogger getChainOfLoggers(){

      AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
      AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
      AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);

      errorLogger.setNextLogger(fileLogger);
      fileLogger.setNextLogger(consoleLogger);

      return errorLogger;	
   }

   public static void main(String[] args) {
      AbstractLogger loggerChain = getChainOfLoggers();

      loggerChain.logMessage(AbstractLogger.INFO, 
         "This is an information.");

      loggerChain.logMessage(AbstractLogger.DEBUG, 
         "This is an debug level information.");

      loggerChain.logMessage(AbstractLogger.ERROR, 
         "This is an error information.");
   }
}

Étape 4

Vérifiez la sortie.

Standard Console::Logger: This is an information.
File::Logger: This is an debug level information.
Standard Console::Logger: This is an debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.