责任链模式

✍ dations ◷ 2025-08-23 09:52:43 #软件设计模式

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

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

相关

  • 核定位信号核定位序列(或称核定位信号;英语:nuclear localization signal,NLS;或 nuclear localization sequence)是一段氨基酸序列,作为蛋白质通过核运输进入细胞核的标签。一般来说,核定位信
  • 浓汤浓汤(英语:Stew)是泛指把固体食物材料以红烧、烩、焖、炖等烹调方式煮成液态浓汤的食物。浓汤与中菜的羹不同之处,在于中菜的羮只作饮用,而浓汤除了饮用,一般还可以再煮稠成为肉汁
  • 性别不安性别不安(英语:gender dysphoria),又称性别焦虑、性别不一致,旧称性别认同障碍(英语:gender identity disorder)或易性症,是一个人因为出生时的性别指定而遭受的痛苦。在这种情况下,性
  • 木刻木刻是在木板上刻出反向图像,再印在纸上欣赏的一种版画艺术。中国古代四大发明之一的印刷术是人类文明发展史上的一块重要的里程碑。它由文字印刷和图像印刷两部分组成,而图像
  • 威尼斯双年展威尼斯双年展(意大利语:La Biennale di Venezia)是一个拥有上百年历史的艺术节,是欧洲最重要的艺术活动之一。并与德国卡塞尔文献展、巴西圣保罗双年展并称为世界三大艺术展,并且
  • 淋溶作用淋溶作用是指土壤内的水,使土壤的可溶性物质(矿物质、有机物)被水溶解的作用。为土壤形成的作用,为成土作用环节之一。
  • 介壳虫见内文介壳虫总科(学名:Coccoidea),又名蚧总科,为半翅目胸喙亚目(旧属同翅目,现同翅目合并到半翅目)下面的一个总科,计有23个科,合共8000多种昆虫。这还未计算已灭绝而只剩下化石的14
  • 犬牙犬齿,俗称尖牙,是很多哺乳动物口腔中,位于门齿和臼齿之间的牙齿。每侧上下颚各有一枚,一共四枚。犬齿的外形一般呈尖锥形,其牙根比门齿长而粗大,深入牙槽骨中。犬齿因其形状,犬齿更
  • 路易-亚历山大·贝尔蒂埃路易-亚历山大·贝尔蒂埃,讷沙泰勒亲王(法语:Louis Alexandre Berthier, prince de Neuchâtel;1753年2月20日-1815年6月1日)法国元帅,1808年任法兰西副陆军统帅,拿破仑手下的参谋长
  • 血小板增生症血小板增生症或作血小板增多症。(essential thrombocythemia),是一种血小板过多执行凝血作用而产生的结果。其常见于皮肤表面血小板栓子(结痂)过量,通常此现象很有可能与骨髓