责任链模式

✍ dations ◷ 2025-11-04 19:01:41 #软件设计模式

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

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

相关

  • 器官移植人体解剖学 - 人体生理学 组织学 - 胚胎学 人体寄生虫学 - 免疫学 病理学 - 病理生理学 细胞学 - 营养学 流行病学 - 药理学 - 毒理学器官移植(德语:Organtransplantation,英
  • 抽血检查血液检查(英语:Blood test),是指通过采血以获得受检者的血液,并利用其进行临床检查以获取受检者的健康状况。主要通过医检师进行检验。血液检查主要用于判断患者在一定时间内的身
  • 安科纳安科纳(意大利语:Ancona)位于意大利中东部亚得里亚海畔,威尼斯南部的小都市。亦是马尔凯区和安科纳省的首府。古罗马时代起就是个繁荣的港口城市,至中世纪,安科纳经常被哥特人、伦
  • 各大区GDP总值本条目为主要年份法国各大区的区内生产总值列表。以法国官方统计资料为依据,以法国本币欧元为基数。为增加可比性,辅以美元折算,美元折算汇率按联合国发布历年各国GDP本币与美
  • 伊朗名称在西方世界,波斯(Persia,或者是Persia的任一个同源字)在历史上曾是伊朗的俗称。在公元1,935年的伊朗人的新年诺鲁兹节,巴列维王朝皇帝礼萨汗(Reza Shah Pahlavi)要求外国代表在国与
  • 宣慰司宣慰使司,简称宣慰司。元朝、明朝、清朝官署名,常设的地方行政机构,在边疆少数民族地区执掌军民事务。元代道分两种:一种是掌军民之政的宣慰使司,一种是遍设全国各地职掌司法。宣
  • 阿布哈兹阿沙阿沙(阿布哈兹语:аҧсар, āpsār)是阿布哈兹共和国的一种货币。从2008年开始发行,1、10、25、50和100阿沙面额的硬币陆续发行,他们虽是阿布哈兹共和国的法定货币,但其使用非
  • 2019冠状病毒病法属波利尼西亚疫情3月3月4月4月最近15日最近15日2019冠状病毒病法属波利尼西亚疫情,介绍在2019新型冠状病毒疫情中,在法属波利尼西亚发生的情况。2020年3月11日,法属波利尼西亚宣布塔希提岛确诊
  • 联合国教科文组织人类非物质文化遗产代表作名录中国项目《中国人类非物质文化遗产代表作名录》是联合国教育、科学及文化组织《保护非物质文化遗产公约》缔约国中华人民共和国依据该公约在国际一级保护的非物质文化遗产项目。迄今
  • 网站镜像镜像,原意是光学里指的物体在镜面中所成之像。引申到计算机网络上,网站镜像是指对网站内容的拷贝。镜像通常用于为相同信息内容提供不同的源,特别是在下载量大的时候提供了一种