责任链模式

✍ dations ◷ 2025-11-26 06:05:29 #软件设计模式

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

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

相关

  • 无法理解别人的话感觉性失语症 ,又被称为韦尼克氏失语症 , 流畅失语症 ,或接受性失语症。此类患者有语言理解障碍,患者的阅读能力或了解他人谈话内容的能力低下。虽然患者能够说初具语法、速
  • 阔鼻小目阔鼻小目(学名:Platyrrhini),又称新世界猴,是产于中美洲与南美洲的四科灵长目动物,包括卷尾猴科、青猴科、僧面猴科和蜘蛛猴科。新世界猴与旧世界猴合称为猴。灵长类包括660多个现
  • 凯林威廉·乔治·凯林(英语:William George Kaelin,1957年11月23日-),生于纽约,美国癌症学家、哈佛医学院教授。2019年诺贝尔生理学或医学奖得主。凯林1979年获杜克大学化学学士学位,198
  • Trussardi楚萨迪(意大利语:Trussardi),是意大利服饰品牌,成立于1911年。1911年由Dante Trussardi先生创立于意大利贝加莫省阿尔梅,原是手套工厂,曾是英国皇家御用手套供应商。二次大战以后,创
  • 人妻人妻(日文汉字又可写成他妻)即“人家的妻子”或“人家的老婆”。而“人家的丈夫”则称为人夫。在古汉语,人妻是指已婚妇女。而在现代日本用语中则通常为丈夫除外其他人对该妇女
  • 黄道面黄道面(plane of the ecliptic)的定义中,是假想地球是不动的,而太阳绕地球旋转。黄道面即为太阳绕地球旋转的轨道平面,目前与地球赤道面交角为23°26'。由于月球和其它行星等天体
  • 赫鲁晓夫楼赫鲁晓夫楼(俄语:Хрущёвка,转写:Khrushchyovka)是一种造价低廉、盒子式或砌体结构三至五层公寓的公寓楼,苏联在20世纪60年代的尼基塔·赫鲁晓夫执政时期大量兴建,并以他的
  • 二十一烷二十一烷(英语:heneicosane)是含有21个碳原子的直链烷烃,化学式为C21H44或CH3(CH2)19CH3,外观为无色蜡状固体,化学性质相当安定。其衍生物二十一烷酸(CH3(CH2)19COOH)可做为制备脂
  • 剑桥大学彼得学院剑桥大学彼得学院(英语:Peterhouse, Cambridge) 始建于1284年,是剑桥大学建立最早的学院。彼得学院现有284名本科生,130名研究生和45名院士,是剑桥大学最小的学院。彼得学院的建
  • 安畔锡安畔锡(韩语:안판석,1961年-),韩国电视剧导演。