责任链模式

✍ dations ◷ 2025-09-19 04:26:58 #软件设计模式

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

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

相关

  • 欧美大陆欧美大陆(Euramerica)又名劳俄大陆(Laurussia)、老红砂岩大陆(Old Red Continent )是个史前大陆,形成于泥盆纪时期,由劳伦大陆与波罗地大陆碰撞、合并而成(造成加里东造山运动)。在二
  • 欧几里得欧几里得(希腊语:Ευκλειδης,前325年-前265年),有时被称为亚历山大里亚的欧几里得,以便区别于墨伽拉的欧几里得,希腊化时代的数学家,被称为“几何学之父”。他活跃于托勒密一
  • 中央圣马丁艺术与设计学院中央圣马丁艺术与设计学院(Central Saint Martins College of Art and Design,简称: 中央圣马丁、CSM)是英格兰一所著名的艺术和设计学院,属于伦敦艺术大学的一部分。1989年,中央
  • B淋巴细胞B细胞(B淋巴球)有时称之为“朝囊定位细胞”(bursa oriented cells),这是因为它们首次在鸡的腔上囊(Bursa of Fabricius)被提及的关系。在肠道的派亚氏腺体(Peyer's glands)中的淋巴组
  • 新地岛新地岛(俄语:Новая Земля),俄罗斯在北冰洋内一群岛,属阿尔汉格尔斯克州管辖,全年冰封。该岛位于巴伦支海和喀拉海之间,是乌拉尔山脉在北冰洋内的延伸。群岛面积约为8.3万
  • 快门快门也叫光闸,(粤语区有按英文"Shutter"音译成“失打”一词)是照相机中控制曝光时间的重要部件,快门时间越短,曝光时间越少。依照快门在相机中的位置分类为:最初的快门只是一个镜
  • 沃尔庇杯沃尔皮杯 (意大利语:Coppa Volpi)是威尼斯电影节颁发的两个正式奖项,用以表彰正式竞赛单元中杰出的演员,分别授予最佳男演员奖与最佳女演员奖。本奖项以威尼斯电影节创办人朱塞
  • 尤纳斯尤纳斯·卡兹劳斯卡斯(立陶宛语:Jonas Kazlauskas,1954年11月21日-),前苏联及立陶宛篮球巨星,先后出任球员和教练等职司,曾任立陶宛国家男子篮球队、中国男篮、希腊国家男子篮球队主
  • 欧洲联盟条约欧洲联盟条约(Treaty on European Union,简称TEU)是欧洲联盟的宪制性文本、欧盟法的重要组成部分。该条约有多次著名的重大版本更迭,您可能指的是:关于现时版本的欧洲联盟条约,请
  • 2010 SMTOWN Live世界巡回演唱会SMTOWN Live '10 World Tour是韩国经纪公司SM娱乐从2010至2011年举办,旗下艺人的联合世界巡回演唱会。这次巡演在六个城市进行,分别在首尔、洛杉矶、上海、东京、巴黎及纽约。