Design Patterns
239 pág.

Design Patterns


DisciplinaEngenharia de Software I5.641 materiais57.743 seguidores
Pré-visualização50 páginas
may act as dispatchers, capable of
sending commands out in a variety of directions, forming a tree of responsibility. In some cases, this can occur
recursively, with processing objects calling higher-up processing objects with commands that attempt to solve some
smaller part of the problem; in this case recursion continues until the command is processed, or the entire tree has
been explored. An XML interpreter might work in this manner.
This pattern promotes the idea of loose coupling, which is considered a programming best practice.
Example
The following code illustrates the pattern with the example of a logging class. Each logging handler decides if any
action is to be taken at this log level and then passes the message on to the next logging handler. Note that this
example should not be seen as a recommendation on how to write logging classes.
Also, note that in a 'pure' implementation of the chain of responsibility pattern, a logger would not pass responsibility
further down the chain after handling a message. In this example, a message will be passed down the chain whether
it is handled or not.
Java
package chainofresp;
abstract class Logger {
 public static int ERR = 3;
 public static int NOTICE = 5;
 public static int DEBUG = 7;
 protected int mask;
 
 // The next element in the chain of responsibility
 protected Logger next;
 
 public Logger setNext(Logger log) {
 next = log;
 return log;
 }
 
 public void message(String msg, int priority) {
 if (priority <= mask) {
 writeMessage(msg);
 }
 if (next != null) {
 next.message(msg, priority);
 }
Chain-of-responsibility pattern 118
 }
 
 abstract protected void writeMessage(String msg);
}
 
class StdoutLogger extends Logger {
 public StdoutLogger(int mask) { 
 this.mask = mask;
 }
 
 protected void writeMessage(String msg) {
 System.out.println(&quot;Writing to stdout: &quot; + msg);
 }
}
 
 
class EmailLogger extends Logger {
 public EmailLogger(int mask) {
 this.mask = mask;
 }
 
 protected void writeMessage(String msg) {
 System.out.println(&quot;Sending via email: &quot; + msg);
 }
}
 
class StderrLogger extends Logger {
 public StderrLogger(int mask) {
 this.mask = mask;
 }
 
 protected void writeMessage(String msg) {
 System.err.println(&quot;Sending to stderr: &quot; + msg);
 }
}
 
public class ChainOfResponsibilityExample {
 public static void main(String[] args) {
 // Build the chain of responsibility
 Logger logger, logger1,logger2;
 logger = new StdoutLogger(Logger.DEBUG);
 logger1 = logger.setNext(new EmailLogger(Logger.NOTICE));
 logger2 = logger1.setNext(new StderrLogger(Logger.ERR));
 
 // Handled by StdoutLogger
 logger.message(&quot;Entering function y.&quot;, Logger.DEBUG);
 
Chain-of-responsibility pattern 119
 // Handled by StdoutLogger and EmailLogger
 logger.message(&quot;Step1 completed.&quot;, Logger.NOTICE);
 
 // Handled by all three loggers
 logger.message(&quot;An error has occurred.&quot;, Logger.ERR);
 }
}
/*
The output is:
 Writing to stdout: Entering function y.
 Writing to stdout: Step1 completed.
 Sending via e-mail: Step1 completed.
 Writing to stdout: An error has occurred.
 Sending via e-mail: An error has occurred.
 Writing to stderr: An error has occurred.
*/
C#
using System;
using System.IO;
namespace ChainOfResponsibility
{
 public enum LogLevel
 {
 Info=1,
 Debug=2,
 Warning=4,
 Error=8,
 FunctionalMessage=16,
 FunctionalError=32,
 All = 63
 }
 /// <summary>
 /// Abstract Handler in chain of responsibility Pattern
 /// </summary>
 public abstract class Logger
 {
 protected LogLevel logMask;
 // The next Handler in the chain
 protected Logger next;
 public Logger(LogLevel mask)
 {
 this.logMask = mask;
Chain-of-responsibility pattern 120
 }
 /// <summary>
 /// Sets the Next logger to make a list/chain of Handlers
 /// </summary>
 public Logger SetNext(Logger nextlogger)
 {
 next = nextlogger;
 return nextlogger;
 }
 public void Message(string msg, LogLevel severity)
 {
 if ((severity & logMask) != 0)
 {
 WriteMessage(msg);
 }
 if (next != null)
 {
 next.Message(msg, severity);
 }
 }
 abstract protected void WriteMessage(string msg);
 }
 public class ConsoleLogger : Logger
 {
 public ConsoleLogger(LogLevel mask)
 : base(mask)
 { }
 
 protected override void WriteMessage(string msg)
 {
 Console.WriteLine(&quot;Writing to console: &quot; + msg);
 }
 }
 public class EmailLogger : Logger
 {
 public EmailLogger(LogLevel mask)
 : base(mask)
 { }
 protected override void WriteMessage(string msg)
 {
 //Placeholder for mail send logic, usually the email 
Chain-of-responsibility pattern 121
configurations are saved in config file.
 Console.WriteLine(&quot;Sending via email: &quot; + msg);
 }
 }
 class FileLogger : Logger
 {
 public FileLogger(LogLevel mask)
 : base(mask)
 { }
 protected override void WriteMessage(string msg)
 {
 //Placeholder for File writing logic
 Console.WriteLine(&quot;Writing to Log File: &quot; + msg);
 }
 }
 public class Program
 {
 public static void Main(string[] args)
 {
 // Build the chain of responsibility
 Logger logger, logger1, logger2;
 logger1 = logger = new ConsoleLogger(LogLevel.All);
 logger1 = logger1.SetNext(new 
EmailLogger(LogLevel.FunctionalMessage | LogLevel.FunctionalError));
 logger2 = logger1.SetNext(new FileLogger(LogLevel{{Not a 
typo|.}}Warning | LogLevel.Error));
 // Handled by ConsoleLogger
 logger.Message(&quot;Entering function ProcessOrder().&quot;, 
LogLevel.Debug);
 logger.Message(&quot;Order record retrieved.&quot;, LogLevel.Info);
 // Handled by ConsoleLogger and FileLogger
 logger.Message(&quot;Customer Address details missing in Branch 
DataBase.&quot;, LogLevel.Warning);
 logger.Message(&quot;Customer Address details missing in 
Organization DataBase.&quot;, LogLevel.Error);
 // Handled by ConsoleLogger and EmailLogger
 logger.Message(&quot;Unable to Process Order ORD1 Dated D1 For 
Customer C1.&quot;, LogLevel.FunctionalError);
 // Handled by ConsoleLogger and EmailLogger
 logger.Message(&quot;Order Dispatched.&quot;, 
Chain-of-responsibility pattern 122
LogLevel.FunctionalMessage);
 }
 }
}
/* Output
Writing to console: Entering function ProcessOrder().
Writing to console: Order record retrieved.
Writing to console: Customer Address details missing in Branch 
DataBase.
Writing to Log File: Customer Address details missing in Branch 
DataBase.
Writing to console: Customer Address details missing in Organization 
DataBase.
Writing to Log File: Customer Address details missing in Organization 
DataBase.
Writing to console: Unable to