跳转到内容

责任链

25% developed
来自维基教科书,开放的书籍,开放的世界

代理 计算机科学设计模式
责任链
命令

责任链模式的各种示例。

Java 实现

下面是该模式在 Java 中的示例。日志记录器使用一系列日志记录器创建,每个日志记录器都配置了不同的日志级别。

import java.util.Arrays;
import java.util.EnumSet;
import java.util.function.Consumer;

@FunctionalInterface
public interface Logger {
    public enum LogLevel {
        INFO, DEBUG, WARNING, ERROR, FUNCTIONAL_MESSAGE, FUNCTIONAL_ERROR;

        public static LogLevel[] all() {
            return values();
        }
    }

    abstract void message(String msg, LogLevel severity);

    default Logger appendNext(Logger nextLogger) {
        return (msg, severity) -> {
            message(msg, severity);
            nextLogger.message(msg, severity);
        };
    }

    static Logger writeLogger(LogLevel[] levels, Consumer<String> stringConsumer) {
        EnumSet<LogLevel> set = EnumSet.copyOf(Arrays.asList(levels));
        return (msg, severity) -> {
            if (set.contains(severity)) {
                stringConsumer.accept(msg);
            }
        };
    }

    static Logger consoleLogger(LogLevel... levels) {
        return writeLogger(levels, msg -> System.err.println("Writing to console: " + msg));
    }

    static Logger emailLogger(LogLevel... levels) {
        return writeLogger(levels, msg -> System.err.println("Sending via email: " + msg));
    }

    static Logger fileLogger(LogLevel... levels) {
        return writeLogger(levels, msg -> System.err.println("Writing to Log File: " + msg));
    }
}

class Runner {
    public static void main(String[] args) {
        // Build an immutable chain of responsibility
        Logger logger = consoleLogger(LogLevel.all())
                .appendNext(emailLogger(LogLevel.FUNCTIONAL_MESSAGE, LogLevel.FUNCTIONAL_ERROR))
                .appendNext(fileLogger(LogLevel.WARNING, LogLevel.ERROR));

        // Handled by consoleLogger since the console has a LogLevel of all
        logger.message("Entering function ProcessOrder().", LogLevel.DEBUG);
        logger.message("Order record retrieved.", LogLevel.INFO);

        // Handled by consoleLogger and emailLogger since emailLogger implements Functional_Error & Functional_Message
        logger.message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel.FUNCTIONAL_ERROR);
        logger.message("Order Dispatched.", LogLevel.FUNCTIONAL_MESSAGE);

        // Handled by consoleLogger and fileLogger since fileLogger implements Warning & Error
        logger.message("Customer Address details missing in Branch DataBase.", LogLevel.WARNING);
        logger.message("Customer Address details missing in Organization DataBase.", LogLevel.ERROR);
    }
}

以下 Java 代码使用日志记录类示例说明了该模式。每个日志记录处理程序都会决定是否需要在该日志级别采取任何操作,然后将消息传递给下一个日志记录处理程序。请注意,此示例不应被视为如何编写日志记录类的建议。

此外,请注意,在“纯”的责任链模式实现中,日志记录器在处理消息后不会将责任传递给链中的更下层。在此示例中,无论消息是否被处理,都会将其传递到链中。

abstract class Logger {

    public static final int ERR = 3;
    public static final int NOTICE = 5;
    public static final int DEBUG = 7;
    private int mask;

    // The next element in the chain of responsibility
    private Logger next;

    public Logger(int mask) {
        this.mask = mask;
    }

    public Logger setNext(Logger l) {
        next = l;
        return l;
    }

    public void message(String msg, int priority) {
        if (priority <= mask) {
            writeMessage(msg);
        }
        if (next != null) {
            next.message(msg, priority);
        }
    }
   
    abstract protected void writeMessage(String msg);

}
class StdoutLogger extends Logger {

    public StdoutLogger(int mask) {
        super(mask);
    }

    protected void writeMessage(String msg) {
        System.out.println("Writing to stdout: " + msg);
    }

}
class EmailLogger extends Logger {

    public EmailLogger(int mask) {
        super(mask);
    }

    protected void writeMessage(String msg) {
        System.out.println("Sending via email: " + msg);
    }

}
class StderrLogger extends Logger {

    public StderrLogger(int mask) {
        super(mask);
    }

    protected void writeMessage(String msg) {
        System.err.println("Sending to stderr: " + msg);
    }

}
public class ChainOfResponsibilityExample {

    public static void main(String[] args) {
        // Build the chain of responsibility
        Logger l,l1;
        l1 = l = new StdoutLogger(Logger.DEBUG);
        l1 = l1.setNext(new EmailLogger(Logger.NOTICE));
        l1 = l1.setNext(new StderrLogger(Logger.ERR));

        // Handled by StdoutLogger
        l.message("Entering function y.", Logger.DEBUG);

        // Handled by StdoutLogger and EmailLogger
        l.message("Step1 completed.", Logger.NOTICE);

        // Handled by all three loggers
        l.message("An error has occurred.", Logger.ERR);
    }

}

输出是

  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.

以下是该模式在 Java 中的另一个示例。在此示例中,我们有不同的角色,每个角色都有一个固定的购买力限额和一个继任者。每次角色中的用户收到购买请求时,如果超过了他的限额,他只需将该请求传递给他的继任者。

带有抽象方法 processRequest 的抽象类 PurchasePower。

abstract class PurchasePower {

    protected double final base = 500;
    protected PurchasePower successor;

    public void setSuccessor(PurchasePower successor) {
        this.successor = successor;
    }

    abstract public void processRequest(PurchaseRequest request);

}

上面抽象类的四种实现:经理、主管、副总裁、总裁

class ManagerPPower extends PurchasePower {

    private double final ALLOWABLE = 10 * base;

    public void processRequest(PurchaseRequest request) {
        if(request.getAmount() < ALLOWABLE) {
            System.out.println("Manager will approve $"+ request.getAmount());
        }
        else if(successor != null) {
            successor.processRequest(request);
        }
    }

}
class DirectorPPower extends PurchasePower {

    private double final ALLOWABLE = 20 * base;

    public void processRequest(PurchaseRequest request) {
        if(request.getAmount() < ALLOWABLE) {
            System.out.println("Director will approve $"+ request.getAmount());
        }
        else if(successor != null) {
            successor.processRequest(request);
        }
    }

}
class VicePresidentPPower extends PurchasePower {

    private double final ALLOWABLE = 40 * base;

    public void processRequest(PurchaseRequest request) {
        if(request.getAmount() < ALLOWABLE) {
            System.out.println("Vice President will approve $" + request.getAmount());
        }
        else if(successor != null) {
            successor.processRequest(request);
        }
    }
}
class PresidentPPower extends PurchasePower {

    private double final ALLOWABLE = 60 * base;
   
    public void processRequest(PurchaseRequest request) {
        if(request.getAmount() < ALLOWABLE) {
            System.out.println("President will approve $" + request.getAmount());
        }
        else {
            System.out.println( "Your request for $" + request.getAmount() + " needs a board meeting!");
        }
    }

}

带有 Getter 方法的 PurchaseRequest 类,这些方法在此示例中保留请求数据。

class PurchaseRequest {
 
    private int number;
    private double amount;
    private String purpose;

    public PurchaseRequest(int number, double amount, String purpose) {
        this.number = number;
        this.amount = amount;
        this.purpose = purpose;
    }

    public double getAmount() {
        return amount;
    }
    public void setAmount(double amt)  {
        amount = amt;
    }
   
    public String getPurpose() {
        return purpose;
    }
    public void setPurpose(String reason) {
        purpose = reason;
    }

    public int getNumber(){
        return number;
    }
    public void setNumber(int num) {
        number = num;
    }

}

这里是一个使用示例,继任者按以下方式设置:经理 -> 主管 -> 副总裁 -> 总裁

class CheckAuthority {

    public static void main(String[] args) {
        ManagerPPower manager = new ManagerPPower();
        DirectorPPower director = new DirectorPPower();
        VicePresidentPPower vp = new VicePresidentPPower();
        PresidentPPower president = new PresidentPPower();
        manager.setSuccessor(director);
        director.setSuccessor(vp);
        vp.setSuccessor(president);
       
        //enter ctrl+c to kill.
        try{
            while (true) {
                System.out.println("Enter the amount to check who should approve your expenditure.");
                System.out.print(">");
                double d = Double.parseDouble(new BufferedReader(new InputStreamReader(System.in)).readLine());
                manager.processRequest(new PurchaseRequest(0, d, "General"));
           }
        }
        catch(Exception e){
            System.exit(1);
        }  
    }

}
Python 实现
"""
Chain of responsibility pattern example.
"""
from abc import ABCMeta, abstractmethod
from enum import Enum, auto

class LogLevel(Enum):
    """ Log Levels Enum."""
    NONE = auto()
    INFO = auto()
    DEBUG = auto()
    WARNING = auto()
    ERROR = auto()
    FUNCTIONAL_MESSAGE = auto()
    FUNCTIONAL_ERROR = auto()
    ALL = auto()

class Logger:
    """Abstract handler in chain of responsibility pattern."""
    __metaclass__ = ABCMeta

    next = None

    def __init__(self, levels) -> None:
        """Initialize new logger.

        Arguments:
            levels (list[str]): List of log levels.
        """
        self.log_levels = []

        for level in levels:
            self.log_levels.append(level)

    def set_next(self, next_logger: Logger):
        """Set next responsible logger in the chain.

        Arguments:
            next_logger (Logger): Next responsible logger.
        Returns: Logger: Next responsible logger.
        """
        self.next = next_logger
        return self.next

    def message(self, msg: str, severity: LogLevel) -> None:
        """Message writer handler.

        Arguments:
            msg (str): Message string.
            severity (LogLevel): Severity of message as log level enum.
        """
        if LogLevel.ALL in self.log_levels or severity in self.log_levels:
            self.write_message(msg)

        if self.next is not None:
            self.next.message(msg, severity)

    @abstractmethod
    def write_message(self, msg: str) -> None:
        """Abstract method to write a message.

        Arguments:
            msg (str): Message string.
        Raises: NotImplementedError
        """
        raise NotImplementedError("You should implement this method.")

class ConsoleLogger(Logger):
    def write_message(self, msg: str) -> None:
        """Overrides parent's abstract method to write to console.

        Arguments:
            msg (str): Message string.
        """
        print("Writing to console:", msg)

class EmailLogger(Logger):
    def write_message(self, msg: str) -> None:
        """Overrides parent's abstract method to send an email.

        Arguments:
            msg (str): Message string.
        """
        print(f"Sending via email: {msg}")

class FileLogger(Logger):
    def write_message(self, msg: str) -> None:
        """Overrides parent's abstract method to write a file.

        Arguments:
            msg (str): Message string.
        """
        print(f"Writing to log file: {msg}")

def main():
    """Building the chain of responsibility."""
    logger = ConsoleLogger([LogLevel.ALL])
    email_logger = logger.set_next(
        EmailLogger([LogLevel.FUNCTIONAL_MESSAGE, LogLevel.FUNCTIONAL_ERROR])
    )
    # As we don't need to use file logger instance anywhere later
    # We will not set any value for it.
    email_logger.set_next(
        FileLogger([LogLevel.WARNING, LogLevel.ERROR])
    )

    # ConsoleLogger will handle this part of code since the message
    # has a log level of all
    logger.message("Entering function ProcessOrder().", LogLevel.DEBUG)
    logger.message("Order record retrieved.", LogLevel.INFO)

    # ConsoleLogger and FileLogger will handle this part since file logger
    # implements WARNING and ERROR
    logger.message(
        "Customer Address details missing in Branch DataBase.",
        LogLevel.WARNING
    )
    logger.message(
        "Customer Address details missing in Organization DataBase.",
        LogLevel.ERROR
    )

    # ConsoleLogger and EmailLogger will handle this part as they implement
    # functional error
    logger.message(
        "Unable to Process Order ORD1 Dated D1 for customer C1.",
        LogLevel.FUNCTIONAL_ERROR
    )
    logger.message("OrderDispatched.", LogLevel.FUNCTIONAL_MESSAGE)

if __name__ == "__main__":
    main()

另一个示例

class Car:
    def __init__(self):
        self.name = None
        self.km = 11100
        self.fuel = 5
        self.oil = 5
 
def handle_fuel(car):
    if car.fuel < 10:
        print "added fuel"
        car.fuel = 100

def handle_km(car):
    if car.km > 10000:
        print "made a car test."
        car.km = 0

def handle_oil(car):
    if car.oil < 10:
        print "Added oil"
        car.oil = 100
 
class Garage:
    def __init__(self):
        self.handlers = []
 
    def add_handler(self, handler):
        self.handlers.append(handler)
 
    def handle_car(self, car):
        for handler in self.handlers:
            handler(car)
 
if __name__ == '__main__':
    handlers = [handle_fuel, handle_km, handle_oil]
    garage = Garage()
 
    for handle in handlers:
        garage.add_handler(handle)
    garage.handle_car(Car())
Crystal 实现
enum LogLevel
  None
  Info
  Debug
  Warning
  Error
  FunctionalMessage
  FunctionalError
  All
end

abstract class Logger
  property log_levels
  property next : Logger | Nil

  def initialize(*levels)
    @log_levels = [] of LogLevel

    levels.each do |level|
      @log_levels << level
    end
  end

  def message(msg : String, severity : LogLevel)
    if @log_levels.includes?(LogLevel::All) || @log_levels.includes?(severity)
      write_message(msg)
    end
    @next.try(&.message(msg, severity))
  end

  abstract def write_message(msg : String)
end

class ConsoleLogger < Logger
  def write_message(msg : String)
    puts "Writing to console: #{msg}"
  end
end

class EmailLogger < Logger
  def write_message(msg : String)
    puts "Sending via email: #{msg}"
  end
end

class FileLogger < Logger
  def write_message(msg : String)
    puts "Writing to Log File: #{msg}"
  end
end

# Program
# Build the chain of responsibility
logger = ConsoleLogger.new(LogLevel::All)
logger1 = logger.next = EmailLogger.new(LogLevel::FunctionalMessage, LogLevel::FunctionalError)
logger2 = logger1.next = FileLogger.new(LogLevel::Warning, LogLevel::Error)

# Handled by ConsoleLogger since the console has a loglevel of all
logger.message("Entering function ProcessOrder().", LogLevel::Debug)
logger.message("Order record retrieved.", LogLevel::Info)

# Handled by ConsoleLogger and FileLogger since filelogger implements Warning & Error
logger.message("Customer Address details missing in Branch DataBase.", LogLevel::Warning)
logger.message("Customer Address details missing in Organization DataBase.", LogLevel::Error)

# Handled by ConsoleLogger and EmailLogger as it implements functional error
logger.message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel::FunctionalError)

# Handled by ConsoleLogger and EmailLogger
logger.message("Order Dispatched.", LogLevel::FunctionalMessage)

输出

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 Process Order ORD1 Dated D1 For Customer C1.
Sending via email: Unable to Process Order ORD1 Dated D1 For Customer C1.
Writing to console: Order Dispatched.
Sending via email: Order Dispatched.
PHP 实现
<?php

abstract class Logger
{

    /**
     * Bitmask flags for severity.
     */
    public const NONE = 0;
    public const INFO = 0b000001;
    public const DEBUG = 0b000010;
    public const WARNING = 0b000100;
    public const ERROR = 0b001000;
    public const FUNCTIONAL_MESSAGE = 0b010000;
    public const FUNCTIONAL_ERROR = 0b100000;
    public const ALL = 0b111111;

    /** @var int A bitmask flag from this class. */
    protected int $logMask;

    /** @var \Logger|null An optional next logger to handle the message */
    protected ?Logger $next = null;

    /**
     * Logger constructor.
     *
     * @param int $mask
     *   A bitmask flag from this class.
     */
    public function __construct(int $mask)
    {
        $this->logMask = $mask;
    }

    /**
     * Set next responsible logger in the chain.
     *
     * @param \Logger $nextLogger
     *   Next responsible logger.
     *
     * @return \Logger
     *    Logger: Next responsible logger.
     */
    public function setNext(Logger $nextLogger): Logger
    {
        $this->next = $nextLogger;

        return $nextLogger;
    }

    /**
     * Message writer handler.
     *
     * @param string $msg
     *   Message string.
     * @param int $severity
     *   Severity of message as a bitmask flag from this class.
     *
     * @return $this
     */
    public function message(string $msg, int $severity): Logger
    {
        if ($severity & $this->logMask) {
            $this->writeMessage($msg);
        }
        if ($this->next !== null) {
            $this->next->message($msg, $severity);
        }

        return $this;
    }

    /**
     * Abstract method to write a message
     *
     * @param string $msg
     *   Message string.
     */
    abstract protected function writeMessage(string $msg): void;

}

class ConsoleLogger extends Logger
{

    protected function writeMessage(string $msg): void
    {
        echo "Writing to console: $msg\n";
    }

}

class EmailLogger extends Logger
{

    protected function writeMessage(string $msg): void
    {
        echo "Sending via email: $msg\n";
    }

}

class FileLogger extends Logger
{

    protected function writeMessage(string $msg): void
    {
        echo "Writing to a log file: $msg\n";
    }

}

$logger = new ConsoleLogger(Logger::ALL);
$logger
    ->setNext(new EmailLogger(Logger::FUNCTIONAL_MESSAGE | Logger::FUNCTIONAL_ERROR))
    ->setNext(new FileLogger(Logger::WARNING | Logger::ERROR));

$logger
    // Handled by ConsoleLogger since the console has a loglevel of all
    ->message("Entering function ProcessOrder().", Logger::DEBUG)
    ->message("Order record retrieved.", Logger::INFO)
    // Handled by ConsoleLogger and FileLogger since filelogger implements Warning & Error
    ->message("Customer Address details missing in Branch DataBase.", Logger::WARNING)
    ->message("Customer Address details missing in Organization DataBase.", Logger::ERROR)
    // Handled by ConsoleLogger and EmailLogger as it implements functional error
    ->message("Unable to Process Order ORD1 Dated D1 For Customer C1.", Logger::FUNCTIONAL_ERROR)
    // Handled by ConsoleLogger and EmailLogger
    ->message("Order Dispatched.", Logger::FUNCTIONAL_MESSAGE);

/* 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 a log file: Customer Address details missing in Branch DataBase.
Writing to console: Customer Address details missing in Organization DataBase.
Writing to a log file: Customer Address details missing in Organization DataBase.
Writing to console: Unable to Process Order ORD1 Dated D1 For Customer C1.
Sending via email: Unable to Process Order ORD1 Dated D1 For Customer C1.
Writing to console: Order Dispatched.
Sending via email: Order Dispatched.
*/
Racket 实现
#lang racket

; Define an automobile structure
(struct auto (fuel km oil) #:mutable #:transparent)

; Create an instance of an automobile
(define the-auto (auto 5 1500 7))

; Define handlers

(define (handle-fuel auto)
  (when (< (auto-fuel auto) 10)
    (begin (set-auto-fuel! auto 10)
           (printf "set fuel\n"))))

(define (handle-km auto)
  (when (> (auto-km auto) 10000)
    (begin (set-auto-km! auto 0)
           (printf "made a car test\n"))))

(define (handle-oil auto)
  (when (< (auto-oil auto) 10)
    (begin (set-auto-oil! auto (+ (auto-oil auto) 5))
           (printf "added oil\n"))))

; Apply each handler to the auto
(define (handle-auto handlers auto)
  (unless (null? handlers)
    (begin ((car handlers) auto)
           (handle-auto (cdr handlers) auto))))

(display the-auto)
(newline)

; Handle the auto
(handle-auto (list handle-fuel handle-km handle-oil) the-auto)

(display the-auto)
(newline)
Perl 实现

使用 perl 5.10 和 Moose 的有关各种角色购买力的 Java 示例。

use feature ':5.10';

package PurchasePower;
use Moose;

has successor => ( is => "rw", isa => "PurchasePower" );

sub processRequest {
    my ( $self, $req ) = @_;
    if ( $req->amount < $self->allowable ) {
        printf "%s will approve \$%.2f\n", $self->title, $req->amount;
    }
    elsif ( $self->successor ) {
        $self->successor->processRequest($req);
    }
    else {
        $self->no_match( $req );
    }
}

package ManagerPPower;
use Moose; extends "PurchasePower";
sub allowable {5000}
sub title     {"manager"}

package DirectorPPower;
use Moose; extends "PurchasePower";
sub allowable {10000}
sub title     {"director"}

package VicePresidentPPower;
use Moose; extends "PurchasePower";
sub allowable {20000}
sub title     {"vice-president"}

package PresidentPPower;
use Moose; extends "PurchasePower";
sub allowable {30000}
sub title     {"president"}

sub no_match {
    my ( $self, $req ) = @_;
    printf "your request for \$%.2f will need a board meeting\n", $req->amount;
}

package PurchaseRequest;
use Moose;

has number  => ( is => "rw", isa => "Int" );
has amount  => ( is => "rw", isa => "Num" );
has purpose => ( is => "rw", isa => "Str" );

package main;

my $manager   = new ManagerPPower;
my $director  = new DirectorPPower;
my $vp        = new VicePresidentPPower;
my $president = new PresidentPPower;

$manager->successor($director);
$director->successor($vp);
$vp->successor($president);

print "Enter the amount to check who should approve your expenditure.\n>";
my $amount = readline;
$manager->processRequest(
    PurchaseRequest->new(
        number  => 0,
        amount  => $amount,
        purpose => "General"
    )
);

使用 perl 5.10 和 Moose 的 Perl 示例。

use feature ':5.10';

package Car;
use Moose;

has name => ( is => "rw", default => undef );
has km   => ( is => "rw", default => 11100 );
has fuel => ( is => "rw", default => 5 );
has oil  => ( is => "rw", default => 5 );

sub handle_fuel {
    my $self = shift;
    if ( $self->fuel < 10 ) {
        say "added fuel";
        $self->fuel(100);
    }
}

sub handle_km {
    my $self = shift;
    if ( $self->km > 10000 ) {
        say "made a car test";
        $self->km(0);
    }
}

sub handle_oil {
    my $self = shift;
    if ( $self->oil < 10 ) {
        say "added oil";
        $self->oil(100);
    }
}

package Garage;
use Moose;

has handler => (
    is      => "ro",
    isa     => "ArrayRef[Str]",
    traits  => ['Array'],
    handles => { add_handler => "push", handlers => "elements" },
    default => sub { [] }
);

sub handle_car {
    my ($self, $car) = @_;
    $car->$_ for $self->handlers
}

package main;

my @handlers = qw( handle_fuel handle_km handle_oil );
my $garage   = Garage->new;
$garage->add_handler($_) for @handlers;
$garage->handle_car( Car->new );
C# 实现

此 C# 示例使用日志记录应用程序根据日志级别选择不同的源;

namespace ChainOfResponsibility;

[Flags]
public enum LogLevel
{
    None = 0,                 //        0
    Info = 1,                 //        1
    Debug = 2,                //       10
    Warning = 4,              //      100
    Error = 8,                //     1000
    FunctionalMessage = 16,   //    10000
    FunctionalError = 32,     //   100000
    All = 63                  //   111111
}

/// <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;
    }

    /// <summary>
    /// Sets the Next logger to make a list/chain of Handlers.
    /// </summary>
    public Logger SetNext(Logger nextlogger)
    {
        Logger lastLogger = this;

        while (lastLogger.next != null)
        {
            lastLogger = lastLogger.next;
        }

        lastLogger.next = nextlogger;
        return this;
    }

    public void Message(string msg, LogLevel severity)
    {
        if ((severity & logMask) != 0) // True only if any of the logMask bits are set in severity
        {
            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("Writing to console: " + 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 configurations are saved in config file.
        Console.WriteLine("Sending via email: " + msg);
    }
}

class FileLogger : Logger
{
    public FileLogger(LogLevel mask)
        : base(mask)
    { }

    protected override void WriteMessage(string msg)
    {
        // Placeholder for File writing logic
        Console.WriteLine("Writing to Log File: " + msg);
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        // Build the chain of responsibility
        Logger logger;
        logger = new ConsoleLogger(LogLevel.All)
                         .SetNext(new EmailLogger(LogLevel.FunctionalMessage | LogLevel.FunctionalError))
                         .SetNext(new FileLogger(LogLevel.Warning | LogLevel.Error));

        // Handled by ConsoleLogger since the console has a loglevel of all
        logger.Message("Entering function ProcessOrder().", LogLevel.Debug);
        logger.Message("Order record retrieved.", LogLevel.Info);

        // Handled by ConsoleLogger and FileLogger since filelogger implements Warning & Error
        logger.Message("Customer Address details missing in Branch DataBase.", LogLevel.Warning);
        logger.Message("Customer Address details missing in Organization DataBase.", LogLevel.Error);

        // Handled by ConsoleLogger and EmailLogger as it implements functional error
        logger.Message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel.FunctionalError);

        // Handled by ConsoleLogger and EmailLogger
        logger.Message("Order Dispatched.", 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 Process Order ORD1 Dated D1 For Customer C1.
Sending via email: Unable to Process Order ORD1 Dated D1 For Customer C1.
Writing to console: Order Dispatched.
Sending via email: Order Dispatched.
*/

另一个示例

using System;

  class MainApp
  {
    static void Main()
    {
      // Setup Chain of Responsibility
      Handler h1 = new ConcreteHandler1();
      Handler h2 = new ConcreteHandler2();
      Handler h3 = new ConcreteHandler3();
      h1.SetSuccessor(h2);
      h2.SetSuccessor(h3);

      // Generate and process request
      int[] requests = {2, 5, 14, 22, 18, 3, 27, 20};

      foreach (int request in requests)
      {
        h1.HandleRequest(request);
      }

      // Wait for user
      Console.Read();
    }
  }

  // "Handler"
  abstract class Handler
  {
    protected Handler successor;

    public void SetSuccessor(Handler successor)
    {
      this.successor = successor;
    }

    public abstract void HandleRequest(int request);
  }

  // "ConcreteHandler1"
  class ConcreteHandler1 : Handler
  {
    public override void HandleRequest(int request)
    {
      if (request >= 0 && request < 10)
      {
        Console.WriteLine("{0} handled request {1}",
          this.GetType().Name, request);
      }
      else if (successor != null)
      {
        successor.HandleRequest(request);
      }
    }
  }

  // "ConcreteHandler2"
  class ConcreteHandler2 : Handler
  {
    public override void HandleRequest(int request)
    {
      if (request >= 10 && request < 20)
      {
        Console.WriteLine("{0} handled request {1}",
          this.GetType().Name, request);
      }
      else if (successor != null)
      {
        successor.HandleRequest(request);
      }
    }
  }

  // "ConcreteHandler3"
  class ConcreteHandler3 : Handler
  {
    public override void HandleRequest(int request)
    {
      if (request >= 20 && request < 30)
      {
        Console.WriteLine("{0} handled request {1}",
          this.GetType().Name, request);
      }
      else if (successor != null)
      {
        successor.HandleRequest(request);
      }
    }
  }


Clipboard

待办事项
添加更多插图。


代理 计算机科学设计模式
责任链
命令


您对该页面有疑问吗?
在此处提问


在本书中创建一个新页面


华夏公益教科书