Řetězec odpovědnosti
Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od
verze recenzované 27. července 2013; kontroly vyžadují
27 úprav .
Řetězec odpovědnosti |
---|
Řetězec odpovědnosti |
|
Typ |
behaviorální |
Účel |
pro organizaci v systému úrovní odpovědnosti |
Související šablony |
Linker |
Popsáno v Návrhové vzory |
Ano |
Řetězec odpovědnosti je vzorec chování navržený tak , aby organizoval úrovně odpovědnosti v systému.
Aplikace
Šablona se doporučuje používat v následujících podmínkách:
- ve vyvinutém systému existuje skupina objektů, které mohou zpracovávat zprávy určitého typu;
- všechny zprávy musí zpracovávat alespoň jeden systémový objekt;
- zprávy v systému jsou zpracovávány podle schématu „zpracuj to sám nebo to předej jinému“, to znamená, že některé zprávy jsou zpracovány na úrovni, kde byly přijaty, zatímco jiné jsou odeslány objektům jiné úrovně.
Příklady
Příklad Delphi
Zdrojový kód v
Delphi
unitPattern ; _
rozhraní
používá SysUtils ;
typ
TPurchase = class
public
Číslo : integer ;
Částka : Dvojnásobek ;
Účel : řetězec _
konstruktor Create ( num : integer ; am : Double ; pur : string ) ;
konec ;
IApprover = interface
[ '{3ACA3967-FFCF-48A1-AC45-9A9B98A8DD96}' ]
procedure SetSuccessor ( nástupce : IApprover ) ;
procedura ProcessRequest ( nákup : TPurchase ) ;
konec ;
TApprover = chráněná třída ( TInterfacedObject , IApprover )
FSuccessor
: IApprover ; veřejný postup SetSuccessor ( nástupce : IApprover ) ; procedura ProcessRequest ( nákup : TPurchase ) ; virtuální ; abstraktní ; konec ;
TDirector = class ( TAApprover )
procedure ProcessRequest ( nákup : TPurchase ) ; přepsat ;
konec ;
TVicePresident = class ( TAApprover )
procedure ProcessRequest ( nákup : TPurchase ) ; přepsat ;
konec ;
TPresident = class ( TAApprover )
procedure ProcessRequest ( nákup : TPurchase ) ; přepsat ;
konec ;
implementace
{ TApprover }
postup TApprover . SetSuccessor ( nástupce : IApprover ) ;
begin
FSuccessor := následník ;
konec ;
{ TDirector}
postup TŘeditel . ProcessRequest ( nákup : TPurchase ) ;
začít v
případě nákupu . Částka < 1000 0,0 pak
WriteLn ( Formát ( 'Požadavek schválený ředitelem # %d' , [ nákup . Číslo ]))
jinak if FSuccessor <> nula then
FSuccessor . ProcessRequest ( nákup ) ;
konec ;
{TVicePresident}
postup TVicePrezident . ProcessRequest ( nákup : TPurchase ) ;
začít v
případě nákupu . Částka < 2500 0,0 pak
WriteLn ( Formát ( 'Požadavek schválený viceprezidentem # %d' , [ nákup . Číslo ]))
jinak if FSuccessor <> nula then
FSuccessor . ProcessRequest ( nákup ) ;
konec ;
{TPprezident}
postup TPrezident . ProcessRequest ( nákup : TPurchase ) ;
začít v
případě nákupu . Částka < 10 000 0,0 pak
WriteLn ( Formát ( 'Prezident schválil požadavek # %d' , [ nákup . Číslo ]))
jinak
WriteLn ( Formát ( 'Požadavek č. %d vyžaduje schůzku vedení!' , [ nákup . Číslo ]))
konec ;
{ TPkoupit }
konstruktor TPkoupit . Create ( num : integer ; am : Double ; pur : string ) ;
beginNumber
: = num ; Částka := am ; Účel := pur ; konec ;
konec .
//_________________________________________________________________________
program Behaviorální . ChainOfResponsibility . vzor ;
{$APPTYPE KONZOLE}
používá
SysUtils ,
Vzor v 'Pattern.pas' ;
varDirector
: IApprover ; _ Místopředseda : I Schvalovatel ; Předseda : Schvaluji ; Nákup : TPkoupě ;
begin
ReportMemoryLeaksOnShutDown := DebugHook <> 0 ;
zkuste
Director := TDirector . vytvořit ;
VicePresident := TVicePresident . vytvořit ;
Prezident := TPrezident . vytvořit ;
tryDirector
. _ SetSuccessor ( viceprezident ) ; místopředseda . SetSuccessor ( prezident ) ;
Nákup := TPkoupit . Vytvořit ( 2034 , 35 0,00 , 'Zásoby' ) ;
ředitel . ProcessRequest ( Nákup ) ;
Nákup . zdarma ;
Nákup := TPkoupit . Vytvořit ( 2035 , 3259 0.10 , 'Projekt X' ) ;
ředitel . ProcessRequest ( Nákup ) ;
Nákup . zdarma ;
Nákup := TPkoupit . Vytvořit ( 2036 , 12210 0,00 , 'Projekt Y' ) ;
ředitel . ProcessRequest ( Nákup ) ;
Readln ;
Konečně
nákup . zdarma ;
konec ;
kromě
na E : Exception do
Writeln ( E. Classname , ' : ' , E. Message ) ; konec ; konec .
Příklad PHP 5
Zdrojový kód v
PHP 5.3
jmenný prostor ChainOfResponsibility {
abstraktní třída Logger {
constERR = 3 ; _ const UPOZORNĚNÍ = 5 ; const DEBUG = 7 ;
chráněná $maska ;
// Další prvek v řetězci odpovědností
chráněn $next ;
public function __construct ( $mask ) {
$this -> mask = $mask ;
}
public function setNext ( Logger $log ) {
$this -> next = $log ;
return $log ;
}
public function message ( $msg , $priority ) {
if ( $priority <= $this -> mask ) {
$this -> writeMessage ( $msg );
}
if ( $this -> další != null ) {
$this -> další -> zpráva ( $msg , $priority );
}
}
chráněná abstraktní funkce writeMessage ( $msg );
}
class StdoutLogger rozšiřuje Logger {
chráněná funkce writeMessage ( $msg ) {
echo sprintf ( "Zápis do stdout:%s \n " , $msg );
}
}
class EmailLogger rozšiřuje Logger {
chráněná funkce writeMessage ( $msg ) {
echo sprintf ( "Odeslání přes email:%s \n " , $msg );
}
}
class StderrLogger rozšiřuje Logger {
chráněná funkce writeMessage ( $msg ) {
echo sprintf ( "Odesílání do stderr:%s \n " , $msg );
}
}
//řetězec odpovědnosti
class ChainOfResponsibilityExample {
public function run () {
// sestavení řetězce odpovědnosti
$logger = new StdoutLogger ( Logger :: DEBUG );
$logger1 = $logger -> setNext ( new EmailLogger ( Logger :: UPOZORNĚNÍ ));
$logger2 = $logger1 -> setNext ( new StderrLogger ( Logger :: ERR ));
// Obsluhováno StdoutLoggerem
$logger -> message ( "Zadávání funkce y." , Logger :: DEBUG );
// Obsluhováno StdoutLoggerem a EmailLoggerem
$logger -> message ( "Krok1 dokončen." , Logger :: UPOZORNĚNÍ );
// Obsluhováno všemi třemi loggery
$logger -> message ( "Došlo k chybě." , Logger :: ERR );
}
}
$chain = new ChainOfResponsibilityExample ();
$chain -> spustit ();
}
Příklad Java
Zdroj
Java
balíček chainofresp ;
abstract class Logger {
public static int ERR = 3 ;
public static int UPOZORNĚNÍ = 5 ;
public static int DEBUG = 7 ;
chráněná vnitřní maska ; _
// Další prvek v řetězci odpovědnosti
chráněn Logger next ;
public Logger setNext ( Logger log ) {
next = log ;
vrátit deník ;
}
public void message ( String msg , int priority ) {
if ( priorita <= maska ) {
writeMessage ( msg );
}
if ( next != null ) {
next . zpráva ( msg , priorita );
}
}
abstrakt chráněný void writeMessage ( String msg );
}
class StdoutLogger rozšiřuje Logger {
public StdoutLogger ( int mask ) {
this . maska = maska ;
}
protected void writeMessage ( String msg ) {
Systém . ven . println ( "Zápis do stdout: " + msg );
}
}
class EmailLogger rozšiřuje Logger {
public EmailLogger ( int mask ) {
this . maska = maska ;
}
protected void writeMessage ( String msg ) {
Systém . ven . println ( "Odeslání e-mailem: " + zpráva );
}
}
class StderrLogger extends Logger {
public StderrLogger ( int mask ) {
this . maska = maska ;
}
protected void writeMessage ( String msg ) {
Systém . ven . println ( "Odesílání do stderr: " + msg );
}
}
public class ChainOfResponsibilityExample {
public static void main ( String [] args ) {
// Sestavení řetězce odpovědnosti
Logger logger , logger1 , logger2 ;
logger = new StdoutLogger ( Logger . DEBUG );
logger1 = logger . setNext ( nový EmailLogger ( Logger . UPOZORNĚNÍ ));
logger2 = logger1 . setNext ( nový StderrLogger ( Logger . ERR ));
// Obsluhováno protokolem StdoutLogger . zpráva ( "Zadávání funkce y." , Logger . DEBUG );
// Zpracovává StdoutLogger a EmailLogger
logger . zpráva ( "Krok 1 dokončen." , Logger . UPOZORNĚNÍ );
// Obsluhováno všemi třemi loggery
logger . zpráva ( "Došlo k chybě." , Logger . ERR );
}
}
/*
Výstup je:
Zápis do stdout: Zadání funkce y.
Zápis do stdout: Krok 1 dokončen.
Odeslání e-mailem: Krok 1 dokončen.
Zápis do stdout: Došlo k chybě.
Odesílání e-mailem: Došlo k chybě.
Odesílání do stderr: Došlo k chybě.
*/
Příklad v C#
Zdrojový text v
C#
// Vzor řetězce odpovědnosti -- Strukturální příklad
pomocí System ;
jmenný prostor DoFactory.GangOfFour.Chain.Structural
{
/// <summary>
/// Spouštěcí třída MainApp pro Structural
/// Vzor návrhu řetězce odpovědnosti.
/// </summary>
class MainApp
{
/// <summary>
/// Vstupní bod do konzolové aplikace.
/// </summary>
static void Main ()
{
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1 ();
Handler h2 = new ConcreteHandler2 ();
Handler h3 = new ConcreteHandler3 ();
h1 . SetSuccessor ( h2 );
h2 . SetSuccessor ( h3 );
// Generování a zpracování požadavku
int [] requesty = { 2 , 5 , 14 , 22 , 18 , 3 , 27 , 20 };
foreach ( int request in requests )
{
h1 . HandleRequest ( žádost );
}
// Počkejte na uživatelskou
konzoli . ReadKey ();
}
}
/// <summary>
/// Abstraktní třída 'Handler'
/// </summary>
abstract class Handler
{
protected Handler následník ;
public void SetSuccessor ( nástupce obslužného programu ) { this . následník = nástupce ; }
veřejný abstrakt void HandleRequest ( int request );
}
/// <summary>
/// Třída 'ConcreteHandler1'
/// </summary>
class ConcreteHandler1 : Handler
{
public override void HandleRequest ( int request )
{
if ( request >= 0 && request < 10 )
{
Console . WriteLine ( "{0} zpracoval požadavek {1}" ,
toto . GetType (). Name , request );
}
else if ( následník != null )
{
následník . HandleRequest ( žádost );
}
}
}
/// <summary>
/// Třída 'ConcreteHandler2'
/// </summary>
class ConcreteHandler2 : Handler
{
public override void HandleRequest ( int request )
{
if ( request >= 10 && request < 20 )
{
Console . WriteLine ( "{0} zpracoval požadavek {1}" ,
toto . GetType (). Name , request );
}
else if ( následník != null )
{
následník . HandleRequest ( žádost );
}
}
}
/// <summary>
/// Třída 'ConcreteHandler3'
/// </summary>
class ConcreteHandler3 : Handler
{
public override void HandleRequest ( int request )
{
if ( request >= 20 && request < 30 )
{
Console . WriteLine ( "{0} zpracoval požadavek {1}" ,
toto . GetType (). Name , request );
}
else if ( následník != null )
{
následník . HandleRequest ( žádost );
}
}
}
}
Výstup
zpracovaná žádost ConcreteHandler1 2 zpracovaná žádost ConcreteHandler1 5 zpracovaná žádost ConcreteHandler2 14 zpracovaná žádost ConcreteHandler3 22 zpracovaná žádost ConcreteHandler2 18 zpracovaná žádost ConcreteHandler1 3 zpracovaná žádost ConcreteHandler3 27 zpracovaná žádost ConcreteHandler203 _
Příklad C++
Zdrojový text v
C++
#include <iostream>
/**
* Pomocná třída popisující nějaký zločin
*/
class CriminalAction {
kamarád třída policista ; // Policie má přístup k materiálům vyšetřování
int složitost ; // Složitost případu
const char * popis ; // Stručný popis trestného činu
veřejnost :
CriminalAction ( int complexity , const char * description ) : komplexita ( complexity ), description ( description ) {}
};
/**
* Abstraktní policista, který může vyšetřovat zločiny
*/
třída policista {
chráněno :
int snížení ; // dedukce (schopnost rozplétat složité případy) pro tohoto policistu
Policista * další ; // zručnějšího policajta, který dostane případ, pokud je pro toho současného příliš těžký
virtual void researchConcrete ( const char * description ) {} // aktuální vyšetřování
veřejnost :
Policista ( int deduction ) : deduction ( deduction ), next ( nullptr ) {}
virtuální ~ Policista () {
smazat další ;
}
/**
* Do řetězce odpovědnosti přidává zkušenějšího policistu, který může převzít
* vyšetřování, pokud selže dosavadní
*/
Policista * setNext ( Policista * policista ) {
další = policista ;
vrátit další ;
}
/**
* Policista zahájí vyšetřování, nebo pokud je případ příliš komplikovaný, předá jej zkušenějšímu kolegovi
*/
zrušit vyšetřování ( CriminalAction * CriminalAction ) {
if ( dedukce < kriminální akce -> složitost ) {
if ( další ) {
další -> vyšetřovat ( trestníAkce );
} jinak {
std :: cout << "Tento případ nesmí být nikomu prozrazen." << std :: endl ;
}
} jinak {
vyšetřovatKonkrétní ( kriminálníAkce -> popis );
}
}
};
třída MartinRiggs : veřejný policista {
chráněno :
void researchConcrete ( const char * description ) {
std :: cout << "Vyšetřování případu \" " << popis << " \" pod vedením seržanta Martina Riggse" << std :: endl ;
}
veřejnost :
MartinRiggs ( int dedukce ) : Policista ( dedukce ) {}
};
třída JohnMcClane : veřejný policista {
chráněno :
void researchConcrete ( const char * description ) {
std :: cout << "Vyšetřování \" " << popis << " \" Detektiv John McClane" << std :: endl ;
}
veřejnost :
JohnMcClane ( odpočet int ) : Policista ( odpočet ) {}
};
třída Vincent Hanna : veřejný policista {
chráněno :
void researchConcrete ( const char * description ) {
std :: cout << "Vyšetřování případu \" " << popis << " \" vedené poručíkem Vincentem Hannou" << std :: endl ;
}
veřejnost :
VincentHanna ( odpočet int ) : Policista ( odpočet ) {}
};
int main () {
std :: cout << "VYSTUP:" << std :: endl ;
Policista * policista = nový MartinRiggs ( 3 ); // policista s nejméně vyšetřovací schopností policista
-> setNext ( nový JohnMcClane ( 5 ))
-> setNext ( nový Vincent Hanna ( 8 )); // k němu přidejte dva zkušené kolegy policisty -> vyšetřujte ( new CriminalAction ( 2 , "Drogový obchod z Vietnamu" ));
policista -> vyšetřovat ( nová CriminalAction ( 7 , "Odvážná bankovní loupež v centru Los Angeles" ));
policista -> vyšetřovat ( nová CriminalAction ( 5 , "Série výbuchů v centru New Yorku" ));
návrat 0 ;
}
/**
* VÝSTUP:
* Vyšetřování vietnamského obchodu s drogami od seržanta Martina Riggse
* Vyšetřování Daring Bank Loupež v centru Los Angeles od poručíka Vincenta Hanny
* Vyšetřování série bombových útoků v centru New Yorku v podání detektiva Johna McClaina
*/
Příklad Pythonu
Zdrojový kód v
Pythonu
manipulátory = []
def car_handler ( func ):
handlery . append ( func )
return func
třída Auto :
def __init__ ( self ):
self . jméno = Žádné
já . km = 11100
vlastní . palivo = 5
vlastní . olej = 5
@car_handler
def handle_fuel ( car ):
if car . palivo < 10 :
tisk ( "přidané palivo" )
auto . palivo = 100
@car_handler
def handle_km ( car ):
if car . km > 10000 :
tisk ( "udělal test auta." )
auto . km = 0
@car_handler
def handle_oil ( car ):
if car . olej < 10 :
tisk ( "Přidaný olej" )
auto . olej = 100
class Garáž :
def __init__ ( self , handlery = Žádné ):
self . handlers = handlers nebo []
def add_handler ( self , handler ):
self . manipulátoři . připojit ( obslužný program )
def handle_car ( self , car ):
pro handler in self . psovodi :
psovod ( auto )
if __name__ == '__main__' :
garáž = Garáž ( manipulátory )
auto = Auto ()
garáž . handle_car ( auto )
Odkazy
Poznámky
- ↑ Řetězec odpovědnosti v Delphi