责任链模式

✍ dations ◷ 2025-06-08 00:10:32 #软件设计模式

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

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

相关

  • 结节性多动脉炎结节性多动脉炎(Polyarteritis nodosa, PAN)是一种全身性的坏死血管炎,典型的侵犯对象为中型的小动脉,偶尔会影响到小型的动脉。病人的症状大多以全身的系统性症状表现。可能影
  • 建成区建成区(英语:built-up area)一般指城市中的城市化区域。在中国大陆,《城市规划基本术语标准》(GB/T 50280-98)将“城市建成区(urban built-up area)”定义为“城市行政区内实际已成
  • 清华大学交叉信息研究院清华大学交叉信息研究院,是清华大学下属的交叉信息科学研究实体,由图灵奖获得者姚期智教授领衔。其前身是同样由姚期智教授领导的,后成为交叉信息研究院重要组成部分的理论计算
  • 拉布拉多洋流拉布拉多洋流(Labrador Current)为一个在北大西洋的冰冻洋流由北冰洋南部沿着加拿大拉布拉多省(Labrador)岸边,经过纽芬兰岛,再向南流向新斯科舍。拉布拉多洋流为巴芬岛洋流(Baffin
  • 乌布苏湖乌布苏湖(蒙古语:Увс Нуур;图瓦语:Успа-Холь;俄语:Убсу-Нур)属咸水湖,主体位于蒙古国乌布苏省,东北部属俄罗斯联邦图瓦共和国。平均海拔 759米,面积 3,350 平方
  • 光学隔离器光学隔离器,又称光学二极管,是一种可限制光线向特定方向行进的光学仪器。它通常被用来防止多余的反馈光线进入光学振荡器中,例如激光腔。其运作原理乃为法拉第效应(磁光效应所造
  • 原台南长老教女学校本馆暨讲堂坐标:22°59′31″N 120°13′10″E / 22.991889°N 120.219505°E / 22.991889; 120.219505原台南长老教女学校本馆暨讲堂位于台南市东区,于民国九十一年(2002年)6月25日公告为
  • 潍州潍州,中国古代的州。隋朝开皇十六年(596年)置,治所在下密县(今山东省潍坊市东)。以境有潍水,故名。大业二年(606年)省。唐朝武德二年(619年),复置。治所在北海县(今潍坊市),八年又省。北宋
  • 6.5mm Creedmoor大号步枪底火测试枪管长度:28 英寸 来源:Hornady, SAAMI, C.I.P.6.5毫米口径克里德莫尔弹(英语:6.5mm Creedmoor cartridge),简称6.5mm CM或6.5 CM,是总部位于美国内布拉斯加州格兰
  • 列车组员列车组员(Train Crew),系指于铁路列车上工作,以运转列车及提供旅客服务为常态工作之铁路机构工作人员,包括列车驾驶(或火车司机)、列车长及服勤员。至于一般为了检查或定期监测目