责任链模式

✍ dations ◷ 2025-07-22 16:13:38 #软件设计模式

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

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

相关

  • 己内酰胺己内酰胺(Caprolactam,简称CPL),化学式为(CH2)5C(O)NH的有机化合物,是6-氨基己酸(英语:Aminocaproic acid)(ε-氨基己酸)的内酰胺,也可看作己酸的环状酰胺。纯净的己内酰胺是白色的固体
  • 湖南巡抚湖南巡抚,全称巡抚湖南等处地方提督军务、节制各镇兼理粮饷,官衔从二品。巡抚例兼都察院右副都御史,并兼兵部侍郎衔,加衔后升为正二品。巡抚别称“抚院”、“抚台”、“抚军”,是
  • 泡菜锅汤饭馔泡菜锅 (谚文:김치찌개)是一道来自韩国,带辣味的火锅。以韩国泡菜为原料,加入葱、洋葱、豆腐,海鲜或猪肉两者其中之一。佐以配菜和米饭。此菜用的泡菜以较老者为佳,取其因完
  • 吴忠市吴忠市是中华人民共和国宁夏回族自治区下辖的地级市,位于宁夏中部,黄河东岸。市境东邻陕西省榆林市,南接甘肃省庆阳市,西界中卫市,西北临内蒙古自治区阿拉善盟,北连银川市。地处银
  • 营埔文化营埔文化是台湾中部地区新石器时代重要的史前文化类型,以灰黑色陶器为特征,其分布范围大致分布在台湾中部浊水溪、大肚溪、大甲溪中下游地区的河边阶地和丘陵上。遗址的分布范
  • 利比里亚英语利比里亚英语,指非洲利比里亚人所说的变种英语。这类英语共有四种:通常,利比里亚人不使用这些称呼,而是将所有变种都称为“英语”,而另一方面,“利比里亚英语”有时候也被用来称呼
  • 山东话山东方言,俗称山东话,通常指中国山东省境内及周边地区(辽东半岛、江苏省北部)所使用的汉语。在中国山东地区主要流通的方言均属于官话系统。主要分为山东省西北部的冀鲁官话,胶东
  • 中华人民共和国国务院组成人员现行《中华人民共和国宪法》第八十六条和《中华人民共和国国务院组织法》第二条规定,中华人民共和国国务院现由下列人员组成:现行《宪法》和《国务院组织法》均未提到中国人民
  • ICD-10 第十三章:肌肉骨骼系统和结缔组织疾病M00-M25 关节病M30-M36 全身性结缔组织疾患M40-M54 背部病M60-M79 软组织疾患M80-M94 骨病和软骨病M95-M99 肌肉骨骼系统和结缔组织的其他疾患
  • 非共价作用力指数非共价作用力指数一般来说是根据电子密度(ρ)以及简化密度梯度 (s)来使非共价作用力(NCI)具体化的数值。由实证研究得知非共价作用力在低电子密度下与低简化密度梯度区域相