责任链模式

✍ dations ◷ 2025-11-05 13:33:33 #软件设计模式

责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。

以下的日志类(logging)例子演示了该模式。 每一个logging handler首先决定是否需要在该层做处理,然后将控制传递到下一个logging handler。程序的输出是:

  Writing to debug output: Entering function y.  Writing to debug output: Step1 completed.  Sending via e-mail:      Step1 completed.  Writing to debug output: An error has occurred.  Sending via e-mail:      An error has occurred.  Writing to stderr:       An error has occurred.

注意:该例子不是日志类的推荐实现方式。

同时,需要注意的是,通常在责任链模式的实现中,如果在某一层已经处理了这个logger,那么这个logger就不会传递下去。在我们这个例子中,消息会一直传递到最底层不管它是否已经被处理。

import java.util.*;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 l)    {        next = l;        return this;    }    public final void message( String msg, int priority )    {        if ( priority <= mask )         {            writeMessage( msg );            if ( next != null )            {                next.message( msg, priority );            }        }    }        protected abstract void writeMessage( String msg );}class StdoutLogger extends Logger {    public StdoutLogger( int mask ) { this.mask = mask; }    protected void writeMessage( String msg )    {        System.out.println( "Writting to stdout: " + msg );    }}class EmailLogger extends Logger {    public EmailLogger( int mask ) { this.mask = mask; }    protected void writeMessage( String msg )    {        System.out.println( "Sending via email: " + msg );    }}class StderrLogger extends Logger {    public StderrLogger( int mask ) { this.mask = mask; }    protected void writeMessage( String msg )    {        System.out.println( "Sending to stderr: " + msg );    }}public class ChainOfResponsibilityExample{    public static void main( String args )    {        // Build the chain of responsibility        Logger l = new StdoutLogger( Logger.DEBUG).setNext(                            new EmailLogger( Logger.NOTICE ).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 );    }}

PHP

<?phpabstract class Logger {	const ERR = 3;	const NOTICE = 5;	const DEBUG = 7;	protected $mask;	protected $next; // The next element in the chain of responsibility	public function setNext(Logger $l) {		$this->next = $l;		return $this;	}	abstract public function message($msg, $priority);}class DebugLogger extends Logger {	public function __construct($mask) {		$this->mask = $mask;	}	public function message($msg, $priority) {		if ($priority <= $this->mask) {			echo "Writing to debug output: {$msg}\n";		}		if (false == is_null($this->next)) {			$this->next->message($msg, $priority);		}	}}class EmailLogger extends Logger {	public function __construct($mask) {		$this->mask = $mask;	}	public function message($msg, $priority) {		if ($priority <= $this->mask) {			echo "Sending via email: {$msg}\n";		}		if (false == is_null($this->next)) {			$this->next->message($msg, $priority);		}	}}class StderrLogger extends Logger {	public function __construct($mask) {		$this->mask = $mask;	}	public function message($msg, $priority) {		if ($priority <= $this->mask) {			echo "Writing to stderr: {$msg}\n";		}		if (false == is_null($this->next)) {			$this->next->message($msg, $priority);		}	}}class ChainOfResponsibilityExample {	public function __construct() {		// build the chain of responsibility		$l = new DebugLogger(Logger::DEBUG);		$e = new EmailLogger(Logger::NOTICE);		$s = new StderrLogger(Logger::ERR);				$e->setNext($s);		$l->setNext($e);		$l->message("Entering function y.",		Logger::DEBUG);		// handled by DebugLogger		$l->message("Step1 completed.",			Logger::NOTICE);	// handled by DebugLogger and EmailLogger		$l->message("An error has occurred.",	Logger::ERR);		// handled by all three Loggers	}}new ChainOfResponsibilityExample();?>

Visual Prolog

这是一个用mutex保护对于stream的操作的真实例子。

First the outputStream interface (a simplified version of the real one):

interface outputStream   predicates      write : (...).      writef : (string FormatString, ...).end interface outputStream

This class encapsulates each of the stream operations the mutex. The finally predicate is used to ensure that the mutex is released no matter how the operation goes (i.e. also in case of exceptions). The underlying mutex object is released by a in the mutex class, and for this example we leave it at that.

class outputStream_protected : outputStream   constructors      new : (string MutexName, outputStream Stream).end class outputStream_protected#include @"pfc\multiThread\multiThread.ph"implement outputStream_protected   facts      mutex : mutex.      stream : outputStream.   clauses      new(MutexName, Stream) :-         mutex := mutex::createNamed(MutexName, false), % do not take ownership         stream := Stream.   clauses      write(...) :-         _ = mutex:wait(),  % ignore wait code in this simplified example         finally(stream:write(...), mutex:release()).   clauses      writef(FormatString, ...) :-         _ = mutex:wait(),  % ignore wait code in this simplified example         finally(stream:writef(FormatString, ...), mutex:release()).end implement outputStream_protected

Usage example.

The client uses an outputStream. Instead of receiving the pipeStream directly, it gets the protected version of it.

相关

  • 患者患者,又称病人、病者和病患,是指医疗服务的接受者,大多用来指罹患疾病、或身体受到创伤,而需要医生和护理人员进行治疗的人;动物如遇到相同状况,也可以患者称之。但是对于不用接受
  • 自然哲学家自然哲学是现代自然科学的奠基,主要是思考人对于的自然界的哲学问题--包括自然界和人的相互关系、人造自然和原生自然的关系、自然界的最基本规律等。这当中不少理论,都奠下了
  • 燕山燕山山脉,史称大燕山、碣石山,山名。在河北省和北京市北部,由潮白河河谷直到山海关。东西走向,北面是内蒙古高原,南邻华北平原。主要由石灰岩、花岗岩、玄武岩构成。海拔400-1000
  • 太阳极小期太阳极小期是太阳周期中太阳活动最低的时期,在这段期间太阳黑子和闪焰的活动最少,经常好几天都不会发生。极小期的日期使用12个月的平滑曲线平均值来描述,因此确认极小期的时间
  • 钮扣钮扣,也写成纽扣或钮扣,又称扣子、纽或扣。是服装或其他衣着(如鞋子)上所附有的一个配件,通常是圆形。钮扣通常可用来将两个分离的部分接合,也有一些纯粹只有装饰用途。装饰用途的
  • 米百俵米百俵(こめひゃっぴょう),日本典故,日语原意为一百袋米。在日本江户时代的戊辰战争中败北的长冈藩,百废待兴。长冈藩的一个支藩三根山藩送来一百袋大米作为慰问,但是当时的长冈藩
  • 阿比路录音室阿比路录音室(英语:Abbey Road Studios)是英国唱片公司EMI在1931年11月于伦敦开设的一家录音室。位于伦敦西敏市圣约翰伍德的阿比路。这里曾是披头士、平克·弗洛伊德等众多世
  • span style=color:#FFD700;军事冲突/span战争是动物界普遍的行为,在人类社会,战争则与政治紧密关联,是多个组织和组织之间的有组织性的武装冲突。克劳塞维茨认为“战争是政治的延续”。以武力为手段,目的是迫使一方服从
  • 恒常所得假说恒常所得假说(英语:Permanent income Hypothesis,缩写为 PIH),由美国经济学家米尔顿·傅利曼所发展出的消费理论,在1957年提出。所谓的恒常所得(permanent income)是指长期的预期平
  • 威廉一世 (奥兰治)威廉一世,奥兰治亲王(荷兰语:Willem I,也称沉默者威廉(荷兰语:Willem de Zwijger)、奥兰治的威廉(荷兰语:Willem van Oranje),1533年4月24日-1584年7月10日)。奥兰治的威廉是尼德兰革命中