Lanțul de responsabilități
Versiunea actuală a paginii nu a fost încă examinată de colaboratori experimentați și poate diferi semnificativ de
versiunea revizuită la 27 iulie 2013; verificările necesită
27 de modificări .
Lanțul de responsabilități |
---|
Lanț de responsabilitate |
|
Tip de |
comportamental |
Scop |
pentru organizarea în sistemul de niveluri de responsabilitate |
Șabloane înrudite |
linker |
Descris în Design Patterns |
da |
Lanțul de responsabilitate este un model de design comportamental conceput pentru a organiza nivelurile de responsabilitate într-un sistem.
Aplicație
Șablonul este recomandat pentru utilizare în următoarele condiții:
- în sistemul dezvoltat există un grup de obiecte care pot procesa mesaje de un anumit tip;
- toate mesajele trebuie să fie procesate de cel puțin un obiect de sistem;
- mesajele din sistem sunt procesate conform schemei „procesează-l singur sau transmite-l altuia”, adică unele mesaje sunt procesate la nivelul la care au fost primite, în timp ce altele sunt trimise la obiecte de un alt nivel.
Exemple
Exemplu Delphi
Cod sursă în
Delphi
unitPattern ; _
interfata
folosește SysUtils ;
tip
TPurchase = clasă
public
Număr : întreg ;
Suma : dubla ;
Scop : șir _
constructor Create ( num : integer ; am : Double ; pur : string ) ;
sfârşitul ;
IApprover = interfață
[ '{3ACA3967-FFCF-48A1-AC45-9A9B98A8DD96}' ]
procedura SetSuccessor ( succesor : IApprover ) ;
procedura ProcessRequest ( cumpărare : TPurchase ) ;
sfârşitul ;
TApprover = clasa ( TInterfacedObject , IApprover )
protejat
FSuccessor : IApprover ;
procedura publică
SetSuccessor ( succesor : IApprover ) ; procedura ProcessRequest ( cumpărare : TPurchase ) ; virtual ; abstract ; sfârşitul ;
TDirector = procedură de clasă ( TApprover )
ProcessRequest ( cumpărare : TPurchase ) ; suprascrie ; sfârşitul ;
TVicePresident = procedură de clasă ( TAApprover )
ProcessRequest ( cumpărare : TPurchase ) ; suprascrie ; sfârşitul ;
TPresident = procedură de clasă ( TApprover )
ProcessRequest ( cumpărare : TPurchase ) ; suprascrie ; sfârşitul ;
implementare
{ TApprover }
procedura TAApprover . SetSuccessor ( succesor : IApprover ) ;
începe
FSuccessor := succesor ;
sfârşitul ;
{ TDirector }
procedura TDirector . ProcessRequest ( cumpărare : TPurchase ) ;
începe
dacă cumpărare . Sumă < 1000 0,0 apoi
WriteLn ( Format ( 'Solicitare aprobată de director # %d' , [ cumpărare . Număr ]))
altfel dacă FSuccessor <> nil , atunci
FSuccessor . ProcessRequest ( cumpărare ) ;
sfârşitul ;
{TVice President}
procedura TVicePreședinte . ProcessRequest ( cumpărare : TPurchase ) ;
începe
dacă cumpără . Sumă < 2500 0,0 apoi
WriteLn ( Format ( 'Solicitare aprobată de vicepreședinte # %d' , [ cumpărare . Număr ]))
altfel dacă FSuccessor <> nil atunci
FSuccessor . ProcessRequest ( cumpărare ) ;
sfârşitul ;
{TPresident}
procedura TPreședinte . ProcessRequest ( cumpărare : TPurchase ) ;
începe
dacă cumpără . Sumă < 10000 0,0 apoi
WriteLn ( Format ( 'Președintele a aprobat cererea # %d' , [ cumpărare . Număr ]))
altfel
WriteLn ( Format ( 'Solicitarea # %d necesită o întâlnire executivă!' , [ cumpărare . Număr ]))
final ;
{ Achiziționare }
constructor TPurchase . Creați ( num : întreg ; am : Double ; pur : șir ) ;
beginNumber
: = num ; Suma := am ; Scop := pur ; sfârşitul ;
sfârşitul .
//________________________________________________________________________
program Comportamental . ChainOfResponsibility . model ;
{$APPTYPE CONSOLE}
folosește
SysUtils ,
Pattern în 'Pattern.pas' ;
varDirector
: IApprover ; _ Vicepreşedinte : I Aprobator ; Președinte : I Aprobator ; Cumpărare : Tpurchase ;
începe
ReportMemoryLeaksOnShutDown := DebugHook <> 0 ;
încercați
Director := TDirector . a crea ;
Vicepreședinte := TVicePresident . a crea ; Președinte := TPreședinte . a crea ;
încercați
Director _ SetSuccessor ( vicepresedinte ) ; Vicepreședinte . SetSuccessor ( Președinte ) ;
Cumpărare := TCumparare . Creați ( 2034 , 35 0,00 , „Rechizite” ) ;
director . ProcessRequest ( Cumpărare ) ;
Achizitioneaza . Gratuit ;
Cumpărare := TCumparare . Creați ( 2035 , 3259 0,10 , „Proiect X” ) ;
director . ProcessRequest ( Cumpărare ) ;
Achiziționare . Gratuit ;
Cumpărare := TCumparare . Creați ( 2036 , 12210 0,00 , „Proiect Y” ) ;
director . ProcessRequest ( Cumpărare ) ;
Readln ;
În sfârșit
Cumpărați . Gratuit ;
sfârşitul ;
cu excepția
E : Excepție pentru Writeln ( E. Classname , ' : ' , E. Message ) ; sfârşitul ; sfârşitul .
Exemplu PHP 5
Cod sursă în
PHP 5.3
spațiu de nume ChainOfResponsibility {
clasa abstractă Logger {
constERR = 3 ; _ const NOTIFICARE = 5 ; const DEBUG = 7 ;
protected $mask ;
// Următorul element din lanțul de responsabilități
protejat $next ;
function public __construct ( $mask ) {
$this -> mask = $mask ;
}
public function setNext ( Logger $log ) {
$this -> next = $log ;
returnează $log ;
}
mesaj public function ( $msg , $priority ) { if ( $priority <= $this -> mask ) { $this -> writeMessage ( $msg ); }
if ( $this -> next != null ) {
$this -> next -> mesaj ( $msg , $priority );
}
}
funcția abstractă protejată writeMessage ( $msg ); }
clasa StdoutLogger extinde Logger {
protected function writeMessage ( $msg ) {
echo sprintf ( "Scrierea in stdout:%s \n " , $msg );
}
}
clasa EmailLogger extinde Logger {
protected function writeMessage ( $msg ) {
echo sprintf ( "Trimit prin email:%s \n " , $msg );
}
}
clasa StderrLogger extinde Logger {
protected function writeMessage ( $msg ) {
echo sprintf ( "Trimiterea catre stderr:%s \n " , $msg );
}
}
//lanțul de responsabilități
clasa ChainOfResponsibilityExample {
public function run () {
// construiește lanțul de responsabilitate
$logger = new StdoutLogger ( Logger :: DEBUG );
$logger1 = $logger -> setNext ( nou EmailLogger ( Logger :: NOTIFICARE ));
$logger2 = $logger1 -> setNext ( nou StderrLogger ( Logger :: ERR ));
// Gestionat de StdoutLogger
$logger -> mesaj ( "Se introduce funcția y." , Logger :: DEBUG );
// Gestionat de StdoutLogger și EmailLogger
$logger -> mesaj ( "Step1 completed." , Logger :: NOTIFICARE );
// Gestionat de toți cei trei loggeri
$logger -> mesaj ( „A apărut o eroare.” , Logger :: ERR );
}
}
$chain = nou ChainOfResponsibilityExample ();
$lant -> rula ();
}
Exemplu Java
Sursa
Java
pachet chainofresp ;
abstract class Logger {
public static int ERR = 3 ;
public static int NOTIFICARE = 5 ;
public static int DEBUG = 7 ;
intmask protejat ; _
// Următorul element din lanțul de responsabilitate
protejat Logger next ;
public Logger setNext ( Logger log ) {
next = log ;
jurnal de returnare ; }
mesaj public void ( String msg , int priority ) { if ( priority <= mask ) { writeMessage ( msg ); } if ( next != null ) { next . mesaj ( msj , prioritate ); } }
abstract protejat void writeMessage ( String msg );
}
clasa StdoutLogger extinde Logger {
public StdoutLogger ( int mask ) {
this . masca = masca ;
}
protejat void writeMessage ( String msg ) {
System . afară . println ( "Scrierea la stdout: " + msg );
}
}
clasa EmailLogger extinde Logger {
public EmailLogger ( int mask ) {
this . masca = masca ;
}
protejat void writeMessage ( String msg ) {
System . afară . println ( "Trimitere prin e-mail: " + msg );
}
}
clasa StderrLogger extinde Logger {
public StderrLogger ( int mask ) {
this . masca = masca ;
}
protejat void writeMessage ( String msg ) {
System . afară . println ( "Se trimite la stderr: " + msg );
}
}
public class ChainOfResponsibilityExample {
public static void main ( String [] args ) {
// Construiește lanțul de responsabilitate
Logger logger , logger1 , logger2 ;
logger = new StdoutLogger ( Logger . DEBUG );
logger1 = logger . setNext ( nou EmailLogger ( Logger . NOTIFICARE ));
logger2 = logger1 . setNext ( nou StderrLogger ( Logger . ERR ));
// Gestionat de StdoutLogger
logger . mesaj ( „Se introduce funcția y.” , Logger . DEBUG );
// Gestionat de StdoutLogger și EmailLogger
logger . mesaj ( „Step1 completed.” , Logger . NOTIFICARE );
// Gestionat de toate cele trei
logger-uri . mesaj ( „A apărut o eroare.” , Logger . ERR );
}
}
/*
Ieșirea este:
Scrierea în stdout: Se introduce funcția y.
Scriere la stdout: Pasul 1 finalizat.
Trimiterea prin e-mail: Pasul 1 finalizat.
Scriere la stdout: a apărut o eroare.
Se trimite prin e-mail: a apărut o eroare.
Se trimite la stderr: a apărut o eroare.
*/
Exemplu în C#
Text sursă în
C#
// Modelul lanțului de responsabilitate -- Exemplu structural
folosind System ;
namespace DoFactory.GangOfFour.Chain.Structural
{
/// <summary>
/// Clasa de pornire MainApp pentru Structural
/// Chain of Responsibility Design Pattern.
/// </summary>
class MainApp
{
/// <summary>
/// Punct de intrare în aplicația consolă.
/// </summary>
static void Main ()
{
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1 ();
Handler h2 = nou ConcreteHandler2 ();
Handler h3 = nou ConcreteHandler3 ();
h1 . SetSuccessor ( h2 );
h2 . SetSuccessor ( h3 );
// Generați și procesați cererea
int [] cereri = { 2 , 5 , 14 , 22 , 18 , 3 , 27 , 20 };
foreach ( cerere int în cereri ) { h1 . HandleRequest ( cerere ); }
// Așteptați
Consola utilizatorului . ReadKey ();
}
}
/// <summary>
/// Clasa abstractă 'Handler'
/// </summary>
abstract class Handler
{
protected Handler succesor ;
public void SetSuccessor ( succesorul Handlerului ) { this . succesor = succesor ; }
public abstract void HandleRequest ( cerere int ); }
/// <summary>
/// Clasa „ConcreteHandler1”
/// </summary>
clasa ConcreteHandler1 : Handler
{
public override void HandleRequest ( int cerere )
{
if ( request >= 0 && request < 10 )
{
Console . WriteLine ( „{0} a gestionat cererea {1}” ,
aceasta . GetType (). Nume , cerere );
}
else if ( succesor != null )
{
succesor . HandleRequest ( cerere );
}
}
}
/// <summary>
/// Clasa „ConcreteHandler2”
/// </summary>
clasa ConcreteHandler2 : Handler
{
public override void HandleRequest ( int cerere )
{
if ( request >= 10 && request < 20 )
{
Console . WriteLine ( „{0} a gestionat cererea {1}” ,
aceasta . GetType (). Nume , cerere );
}
else if ( succesor != null )
{
succesor . HandleRequest ( cerere );
}
}
}
/// <summary>
/// Clasa „ConcreteHandler3”
/// </summary>
clasa ConcreteHandler3 : Handler
{
public override void HandleRequest ( int cerere )
{
if ( request >= 20 && request < 30 )
{
Console . WriteLine ( „{0} a gestionat cererea {1}” ,
aceasta . GetType (). Nume , cerere );
}
else if ( succesor != null )
{
succesor . HandleRequest ( cerere );
}
}
}
}
Ieșire
ConcreteHandler1 gestionată cerere 2
ConcreteHandler1 gestionată cerere 5
ConcreteHandler2 gestionată cerere 14
ConcreteHandler3 gestionată cerere 22
ConcreteHandler2 gestionată cerere 18
ConcreteHandler1 gestionată cerere 3
ConcreteHandler3 gestionată cerere 27
ConcreteHandler3 gestionată cerere 20
Exemplu C++
Text sursă în
C++
#include <iostream>
/**
* Clasa de ajutor care descrie o crimă
*/
clasa CriminalAction {
friend class polițist ; // Poliția are acces la materialele anchetei
int complexitate ; // Complexitatea cazului
const char * descriere ; // Scurtă descriere a infracțiunii
public :
CriminalAction ( int complexity , const char * description ) : complexitate ( complexitate ), descriere ( descriere ) {}
};
/**
* Un ofițer de poliție abstract care poate investiga crime
*/
polițist de clasă {
protejat :
int reducere ; // deducere (capacitatea de a dezlega cazuri complexe) pentru acest polițist
Poliţist * următor ; // un polițist mai priceput care va primi un caz dacă este prea greu pentru cel actual
virtual void investigateConcrete ( const char * description ) {} // investigație reală
public :
Poliţist ( int deducere ) : deducere ( deducere ), următor ( nullptr ) {}
virtual ~ Polițist () {
șterge următorul ;
}
/**
* Adaugă în lanțul de responsabilitate un polițist mai experimentat care poate prelua
* ancheta dacă cea actuală eșuează
*/
Poliţist * setNext ( Poliţist * poliţist ) {
următor = polițist ;
reveniți în continuare ;
}
/**
* Polițistul începe o anchetă sau, dacă cazul este prea complicat, o transmite unui coleg mai experimentat
*/
nul investigare ( CriminalAction * criminalAction ) {
if ( deducere < actiune penala -> complexitate ) {
dacă ( următorul ) {
următorul -> investigați ( Acțiune penală );
} altfel {
std :: cout << "Acest caz nu trebuie dezvăluit nimănui." << std :: endl ;
}
} altfel {
investigateBeton ( criminalAction -> description );
}
}
};
clasa MartinRiggs : polițist public {
protejat :
void investigateConcrete ( const char * description ) {
std :: cout << "Investigarea cazului \" " << descriere << " \" condus de sergent Martin Riggs" << std :: endl ;
}
public :
MartinRiggs ( deducție int ) : polițist ( deducere ) {}
};
clasa JohnMcClane : polițist public {
protejat :
void investigateConcrete ( const char * description ) {
std :: cout << "Investigație \" " << descriere << " \" Detectivul John McClane" << std :: endl ;
}
public :
JohnMcClane ( deducție int ) : polițist ( deducere ) {}
};
clasa Vincent Hanna : polițist public {
protejat :
void investigateConcrete ( const char * description ) {
std :: cout << "Investigarea cazului \" " << descriere << " \" condusa de locotenentul Vincent Hanna" << std :: endl ;
}
public :
VincentHanna ( deducție int ) : polițist ( deducere ) {}
};
int main () {
std :: cout << "OUTPUT:" << std :: endl ;
Polițist * polițist = nou MartinRiggs ( 3 ); // polițist cu cea mai mică abilitate de investigare polițist
-> setNext ( JohnMcClane nou ( 5 ))
-> setNext ( nou Vincent Hanna ( 8 )); // adaugă lui doi colegi polițiști cu experiență -> investigați ( nou CriminalAction ( 2 , „Trafic de droguri din Vietnam” ));
polițist -> investigați ( nou CriminalAction ( 7 , „Un jaf de bancă îndrăzneț în centrul orașului Los Angeles” ));
polițist -> investigați ( nou CriminalAction ( 5 , „Seria de explozii în centrul orașului New York” ));
returnează 0 ;
}
/**
* REZULTARE:
* Investigarea traficului de droguri în Vietnam de către sergentul Martin Riggs
* Investigarea jafului îndrăzneț al băncii din centrul orașului Los Angeles de către locotenentul Vincent Hanna
* Investigarea unei serii de atentate cu bombă în centrul orașului New York, găzduite de detectivul John McClain
*/
Exemplu Python
Cod sursă în
Python
handler = []
def car_handler ( func ):
handler . append ( func )
return func
clasa Car :
def __init__ ( self ):
self . nume = None
self . km = 11100
auto . combustibil = 5
auto . ulei = 5
@car_handler
def handle_fuel ( mașină ):
dacă mașină . combustibil < 10 :
imprimare ( „combustibil adăugat” )
mașină . combustibil = 100
@car_handler
def handle_km ( mașină ):
dacă mașină . km > 10000 :
imprimare ( „a făcut un test de mașină.” )
mașină . km = 0
@car_handler
def handle_oil ( mașină ):
dacă mașină . ulei < 10 :
imprimare ( „Ulei adăugat” )
mașină . ulei = 100
clasa Garaj :
def __init__ ( self , handlers = None ):
self . handlers = handlers sau []
def add_handler ( self , handler ):
self . manipulatori . anexează ( handler )
def handle_car ( self , car ):
pentru handler in self . handlers :
handler ( masina )
if __name__ == '__main__' :
garage = Garage ( handlers )
car = Car ()
garage . handle_car ( masina )
Link -uri
Note
- ↑ Lanțul de responsabilitate în Delphi