责任链模式

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

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

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

相关

  • 科摩罗面积以下资讯是以2010年估计家用电源国家领袖国内生产总值(购买力平价) 以下资讯是以2016年估计国内生产总值(国际汇率) 以下资讯是以2016年估计人类发展指数 以下资讯是以2018
  • 国家卫生健康委1999年规定:印章直径5厘米,中央刊国徽,由国务院制发。中华人民共和国国家卫生健康委员会,官方简称国家卫生健康委,亦简称国家卫健委,是中华人民共和国国务院主管卫生和健康事务的
  • PNA肽核酸(Peptide nucleic acid;PNA)是一种与DNA和RNA相似的化学物质,可经由人工合成制造,用来作为生物学研究或是医学治疗。地球上已知的生物并未发现任何体内拥有PNA的个体。PNA
  • 生命表在精算学中,生命表(也称死亡率表或精算表)是一个表。其中显示一个人在每一个年龄,他在下一个生日前死亡的概率。运用这个概率和统计学算式,可得出多项统计数据,而这些数据也会列入
  • 清河清河区是辽宁省铁岭市下辖的一个市辖区。面积423平方千米,人口10万。邮政编码112003。政府驻清河路63号。下辖2个街道、1个镇、1个乡、1个民族乡:102国道、沈哈高速公路和京哈
  • 保 善保善(1788年 - ?),字翼之,号和斋,蒙古镶白旗人。嘉庆己卯科举人,庚辰科进士。后任翰林院侍讲学生、内阁中书等职。曾祖伊通阿曾任教习;祖父永安,乾隆十七年壬申科进士,官辽宁铁岭县知
  • 穴鸟类穴鸟类(学名:Cavitaves)包括:鹃
  • 普罗克洛普罗克洛(希腊语:Πρόκλος,Próklos,412年2月8日-485年4月17日)也作普罗克洛斯、普洛克罗,最后一位主要的希腊哲学家,新柏拉图主义的集大成者。出生于拜占庭帝国君士坦丁堡。
  • 乔·内森约瑟夫·迈克尔·内森(Joseph Michael Nathan,1974年11月22日-出生于美国德克萨斯州休斯顿)是美国职棒大联盟的终结者。高中和大学时期内森打的是游击手的位置,在被旧金山巨人选
  • 王子岛群王子群岛(土耳其语:Kızıl Adalar,意思是“红色之岛”,常称Adalar“岛屿”),王子群岛位于马尔马拉海中,在土耳其的伊斯坦布尔的东南方约二十公里,王子群岛由九个岛屿组成,其中四个主