コンテンツにスキップ
Wikipedia

Chain of Responsibility パターン

出典: フリー百科事典『ウィキペディア(Wikipedia)』

Chain-of-responsibility パターン, CoR パターンは、オブジェクト指向設計におけるデザインパターンの一つであり、一つのコマンドオブジェクトと一連の処理オブジェクト (processing objects) から構成される。各処理オブジェクトは、処理できるコマンドオブジェクトの種類と、自身が処理できないコマンドオブジェクトをチェーン内の次の処理オブジェクトに渡す方法を記述する情報を保持する。また、新たな処理オブジェクトをチェーンの最後に追加する機構を備える。

標準的な chain-of-responsibility のモデルの派生ハンドラーがディスパッチャとして動作し、コマンドを様々な方向に送出できるようにすることで、いわば tree of responsibility を形成しているものもある。

また、これを再帰的に行うケースもあり、処理オブジェクトが上位の処理オブジェクトを、問題の一部を解決するコマンドとともに呼び出すこともある。こうした場合再帰はコマンドが処理されるか、全てのツリーを巡回するまで継続される。XMLのインタプリタ(パースはするが実行はしない)などがこの例に当てはまるだろう。

このパターンはプログラミングにおいてよく用いられる、疎結合性を促進させる方法である。

[編集 ]

Java

[編集 ]

以下の Java コードは、ロギングクラスの例を用いてこのパターンを示したものである。各ロギングハンドラーはログレベルで何らかのアクションを起こすべきかどうかを判断し、次のロギングハンドラーにメッセージを渡す。

出力:

 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.


この例はロギングクラスをこの方法で書くことを推奨するものではなく、また、CoR の「純粋な」実装では、ロガーがメッセージを処理した後に、その責任を後段に渡すことはない。この例では処理されるかどうかに関係なく、メッセージがチェーンの先に渡される。

importjava.util.*;
abstractclass Logger{
publicstaticfinalintERROR=3;
publicstaticfinalintNOTICE=5;
publicstaticfinalintDEBUG=7;
privatefinalintmask;
protectedLogger(intmask){this.mask=mask;}
// The next element in the chain of responsibility
protectedLoggernext;
publicLoggersetNext(Loggerl){
next=l;
returnthis;
}
publicvoidmessage(Stringmsg,intpriority){
if(priority<=mask){
writeMessage(msg);
if(next!=null){
next.message(msg,priority);
}
}
}

abstractprotectedvoidwriteMessage(Stringmsg);
}
class StdoutLoggerextendsLogger{
publicStdoutLogger(intmask){super(mask);}
@Override
protectedvoidwriteMessage(Stringmsg){
System.out.println("Writting to stdout: "+msg);
}
}
class EmailLoggerextendsLogger{
publicEmailLogger(intmask){super(mask);}
@Override
protectedvoidwriteMessage(Stringmsg){
System.out.println("Sending via email: "+msg);
}
}
class StderrLoggerextendsLogger{
publicStderrLogger(intmask){super(mask);}
@Override
protectedvoidwriteMessage(Stringmsg){
System.out.println("Sending to stderr: "+msg);
}
}
publicclass ChainOfResponsibilityExample{
publicstaticvoidmain(String[]args){
// Build the chain of responsibility
finalLoggerl=
newStdoutLogger(Logger.DEBUG).setNext(
newEmailLogger(Logger.NOTICE).setNext(
newStderrLogger(Logger.ERROR)));
// 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.ERROR);
}
}
<?php
abstract 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();
?>

関連項目

[編集 ]

外部リンク

[編集 ]
GoFによる23種のパターン
生成に関するパターン
構造に関するパターン
振る舞いに関するパターン
並行性に関するパターン
アーキテクチャに関するパターン
その他のパターン
関連する人々
関連項目

AltStyle によって変換されたページ (->オリジナル) /