责任链模式

✍ dations ◷ 2025-03-01 23:36:59 #软件设计模式

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

以下的日志类(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.

相关

  • 吴常信吴常信(1935年11月-),浙江鄞县人。动物遗传育种学家,中国科学院院士。
  • 有机食品有机食品指的是由符合有机农场标准的机构生产的食品。在世界范围内,有机农场标准不一,但一般来说,有机农场致力于对资源的循环再利用,追求生态平衡,以及对生物多样性的保护。在有
  • 解婕翎解婕翎(Manaki Xie Jie Ling,1985年3月24日-),台湾女主持人、演员、模特儿、YouTuber。自2006年开始,解婕翎活跃于展场活动,除舞蹈以外,还尝试主持工作。解婕翎快速且无须背稿的临场
  • 苹果汁苹果汁(英语:apple juice),是从苹果果肉榨出的果汁。苹果汁的制造是先压榨苹果果肉,再将果汁部分过滤出来,通常在工厂中会再进行低温杀菌处理。 由于自制苹果汁的过程必须榨汁再将
  • VC-25A波音VC-25,是美国空军指定的一架客运飞机,一个军事版本的波音747客机。 A型机即VC-25A是VC-25唯一的型号。VC-25最著名之处即作为空军一号,其呼号即带有美国总统的任何一架美
  • 橙皮橙皮又称黄果皮、理陈皮,是芸香科植物香橙的果皮。剥下的果皮经过晒干或烘干而成。香橙含有大量的维生素A,可作为健胃剂。橙皮很早就是中药的一种,味辛微苦,入脾、肺二经。治咳
  • 魏都区魏都区是中华人民共和国河南省许昌市的中心和市辖区。面积67平方公里,2010年人口49.8万。现辖:西大街道、东大街道、西关街道、南关街道、北大街道、五一路街道、高桥营街道、
  • 半数中毒量半数中毒量(median toxic dose,TD50)为毒理学名词,是指一药物或是毒素造成50%比例中毒的剂量。不过若要数值有意义或是可以用在实际应用上,需说明其中毒的种类。半数中毒量的剂量
  • 平原印第安人手语平原印第安人手语(英语:Plains Indian Sign Language,PISL;法语:Langue des Signes Indienne des Plaines;西班牙语:Lenguaje de Signos Indio de las Llanuras),又称平原手语、平原
  • 知识共享许可协议知识共享许可协议(英语:Creative Commons license,或创用CC许可)是一种公共著作权许可协议(英语:Public copyright license),其允许分发受著作权保护的作品。一个创作共享许可用于一