Ansvarskedja
Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från
versionen som granskades den 27 juli 2013; kontroller kräver
27 redigeringar .
Ansvarskedja |
---|
Ansvarskedja |
|
Sorts |
beteendemässiga |
Ändamål |
för organisation i systemet med ansvarsnivåer |
Relaterade mallar |
länk |
Beskrivs i Design Patterns |
Ja |
Ansvarskedja är ett beteendedesignmönster utformat för att organisera ansvarsnivåer i ett system.
Applikation
Mallen rekommenderas för användning under följande förhållanden:
- i det utvecklade systemet finns en grupp objekt som kan bearbeta meddelanden av en viss typ;
- alla meddelanden måste behandlas av minst ett systemobjekt;
- meddelanden i systemet behandlas enligt schemat "bearbeta det själv eller skicka det vidare till en annan", det vill säga vissa meddelanden behandlas på den nivå där de togs emot, medan andra skickas till objekt på en annan nivå.
Exempel
Delphi exempel
Källkod i
Delphi
enhetsmönster ; _
gränssnitt
använder SysUtils ;
typ
TPurchase = klass
offentligt
nummer : heltal ;
Belopp : Dubbel ;
Syfte : sträng _
konstruktor Skapa ( antal : heltal ; am : Dubbel ; pur : sträng ) ;
slut ;
IApprover = gränssnitt
[ '{3ACA3967-FFCF-48A1-AC45-9A9B98A8DD96}' ]
procedur SetSuccessor ( efterföljare : IApprover ) ;
procedur ProcessRequest ( köp : TPurchase ) ;
slut ;
TApprover = klass ( TInterfacedObject , IApprover )
skyddad
FSuccessor : IApprover ;
offentligt
förfarande SetSuccessor ( efterträdare : IApprover ) ;
procedur ProcessRequest ( köp : TPurchase ) ; virtuell ; abstrakt ;
slut ;
TDirector = klass ( TAProver )
procedur ProcessRequest ( köp : TPurchase ) ; åsidosätta ;
slut ;
TVicePresident = klass ( TApprover )
process ProcessRequest ( köp : TPurchase ) ; åsidosätta ;
slut ;
TPresident = class ( TAProver )
process ProcessRequest ( köp : TPurchase ) ; åsidosätta ;
slut ;
genomförande
{ TApprover }
procedur TApprover . SetSuccessor ( efterföljare : IApprover ) ;
börja
FSuccessor := efterföljare ;
slut ;
{ TDirektor }
procedur TDirektor . ProcessRequest ( köp : TPurchase ) ;
börja
om köp . Belopp < 1 000 0,0 sedan
WriteLn ( Format ( 'Regitor godkänd begäran # %d' , [ köp . Antal ]))
annars om FSuccessor <> noll så
FSuccessor . ProcessRequest ( köp ) ;
slut ;
{TVicePresident}
förfarande TV:s vicepresident . ProcessRequest ( köp : TPurchase ) ;
börja
om köp . Belopp < 2500 0,0 sedan
WriteLn ( Format ( 'Vicepresident godkänd begäran # %d' , [ köp . Antal ]))
annars om FSuccessor <> noll så
FSuccessor . ProcessRequest ( köp ) ;
slut ;
{TPresident}
förfarande TPresident . ProcessRequest ( köp : TPurchase ) ;
börja
om köp . Belopp < 10000 0,0 sedan
WriteLn ( Format ( 'President godkänd begäran # %d' , [ köp . Antal ]))
annars
WriteLn ( Format ( 'Request# %d kräver ett exekutivt möte!' , [ köp . Antal ]))
slut ;
{ TPurchase }
konstruktör TPurchase . Skapa ( antal : heltal ; am : Dubbel ; pur : sträng ) ;
beginNumber
: = num ; Belopp := am ; Syfte := pur ; slut ;
slut .
//________________________________________________________________________________
program Beteende . ChainOfResponsibility . mönster ;
{$APPTYPE KONSOL}
använder
SysUtils ,
Pattern i 'Pattern.pas' ;
varDirector
: IApprover ; _ Vicepresident : I Godkännare ; President : Jag godkänner ; Inköp : TPurchase ;
begin
ReportMemoryLeaksOnShutDown := DebugHook <> 0 ;
prova
Director := TDirector . skapa ;
Vicepresident := TV: s vicepresident . skapa ;
President := TPresident . skapa ;
tryDirector
. _ SetSuccessor ( viceordförande ) ; Vicepresident . SetSuccessor ( president ) ;
Köp := TPköp . Skapa ( 2034 , 35 0,00 , 'Supplies' ) ;
regissör . ProcessRequest ( Inköp ) ;
Köp . Gratis ;
Köp := TPköp . Skapa ( 2035 , 3259 0.10 , 'Projekt X' ) ;
regissör . ProcessRequest ( Inköp ) ;
Köp . Gratis ;
Köp := TPköp . Skapa ( 2036 , 12210 0,00 , 'Projekt Y' ) ;
regissör . ProcessRequest ( Inköp ) ;
Läsln ;
Äntligen
köp . Gratis ;
slut ;
förutom
på E : Exception do
Writeln ( E. Classname , ' : ' , E. Message ) ; slut ; slut .
PHP 5 exempel
Källkod i
PHP 5.3
namnområde ChainOfResponsibility {
abstrakt klass Logger {
constERR = 3 ; _ const NOTICE = 5 ; const DEBUG = 7 ;
skyddad $mask ;
// Nästa element i kedjan av ansvar
skyddade $next ;
offentlig funktion __construct ( $mask ) {
$this -> mask = $mask ;
}
public function setNext ( Logger $log ) {
$this -> next = $log ;
returnera $log ;
}
public function message ( $msg , $priority ) {
if ( $priority <= $this -> mask ) {
$this -> writeMessage ( $msg );
}
if ( $this -> next != null ) {
$this -> next -> meddelande ( $msg , $priority );
}
}
skyddad abstrakt funktion writeMessage ( $msg );
}
class StdoutLogger utökar Logger {
skyddad funktion writeMessage ( $msg ) {
echo sprintf ( "Skriver till stdout:%s \n " , $msg );
}
}
class EmailLogger utökar Logger {
skyddad funktion writeMessage ( $msg ) {
echo sprintf ( "Skicka via e-post:%s \n " , $msg );
}
}
class StderrLogger utökar Logger {
skyddad funktion writeMessage ( $msg ) {
echo sprintf ( "Skicka till stderr:%s \n " , $msg );
}
}
//ansvarskedja
klass ChainOfResponsibilityExample {
public function run () {
// bygga ansvarskedjan
$logger = new StdoutLogger ( Logger :: DEBUG );
$logger1 = $logger -> setNext ( ny EmailLogger ( Logger :: NOTICE ));
$logger2 = $logger1 -> setNext ( ny StderrLogger ( Logger :: ERR ));
// Hanteras av StdoutLogger
$logger -> meddelande ( "Kommer in på funktion y." , Logger :: DEBUG );
// Hanteras av StdoutLogger och EmailLogger
$logger -> meddelande ( "Steg 1 slutfört." , Logger :: NOTICE );
// Hanteras av alla tre loggare
$logger -> meddelande ( "Ett fel har inträffat." , Logger :: ERR );
}
}
$chain = new ChainOfResponsibilityExample ();
$kedja -> kör ();
}
Java-exempel
Java -källa
paket chainofresp ;
abstrakt klass Logger {
public static int ERR = 3 ;
public static int NOTICE = 5 ;
public static int DEBUG = 7 ;
skyddad intmask ; _
// Nästa element i ansvarskedjan
skyddade Logger nästa ;
public Logger setNext ( Logger log ) {
next = log ;
returlogg ; _ }
public void message ( String msg , int priority ) {
if ( prioritet <= mask ) {
writeMessage ( msg );
}
if ( nästa != null ) {
nästa . meddelande ( medd. , prioritet );
}
}
abstrakt skyddad void writeMessage ( String msg );
}
class StdoutLogger utökar Logger {
public StdoutLogger ( int mask ) {
detta . mask = mask ;
}
protected void writeMessage ( String msg ) {
System . ut . println ( "Skriver till stdout: " + msg );
}
}
class EmailLogger utökar Logger {
public EmailLogger ( int mask ) {
this . mask = mask ;
}
protected void writeMessage ( String msg ) {
System . ut . println ( "Skicka via e-post: " + msg );
}
}
class StderrLogger utökar Logger {
public StderrLogger ( int mask ) {
detta . mask = mask ;
}
protected void writeMessage ( String msg ) {
System . ut . println ( "Skicka till stderr: " + msg );
}
}
public class ChainOfResponsibilityExample {
public static void main ( String [] args ) {
// Bygg ansvarskedjan
Logger logger , logger1 , logger2 ;
logger = new StdoutLogger ( logger . DEBUG );
logger1 = logger . setNext ( ny EmailLogger ( logger . MEDDELANDE ));
logger2 = logger1 . setNext ( ny StderrLogger ( Logger . ERR ));
// Hanteras av StdoutLogger-
logger . meddelande ( "Kommer in på funktion y." , Logger . DEBUG );
// Hanteras av StdoutLogger och EmailLogger
logger . meddelande ( "Steg 1 slutfört." , Logger . NOTICE );
// Hanteras av alla tre
loggare . meddelande ( "Ett fel har inträffat." , Logger . ERR );
}
}
/*
Utdata är:
Skriver till stdout: Går in på funktion y.
Skriva till stdout: Steg 1 slutfört.
Skickar via e-post: Steg 1 slutfört.
Skriver till stdout: Ett fel har uppstått.
Skickar via e-post: Ett fel har uppstått.
Skickar till stderr: Ett fel har uppstått.
*/
Exempel i C#
Källtext i
C#
// Ansvarskedjans mönster -- Strukturellt exempel
använder System ;
namnutrymme DoFactory.GangOfFour.Chain.Structural
{
/// <sammanfattning>
/// MainApp-startklass för Structural
/// Chain of Responsibility Design Pattern.
/// </summary>
class MainApp
{
/// <summary>
/// Ingångspunkt till konsolapplikationen.
/// </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 );
// Generera och bearbeta begäran
int [] requests = { 2 , 5 , 14 , 22 , 18 , 3 , 27 , 20 };
foreach ( int request in requests )
{
h1 . HandleRequest ( förfrågan );
}
// Vänta på
användarkonsolen . ReadKey ();
}
}
/// <summary>
/// Abstraktklassen 'Handler'
/// </summary>
abstrakt klass Handler
{
protected Handler successor ;
public void SetSuccessor ( hanterare efterföljare )
{
detta . efterträdare = efterträdare ;
}
public abstract void HandleRequest ( int request );
}
/// <summary>
/// Klassen 'ConcreteHandler1'
/// </summary>
klassen ConcreteHandler1 : Handler
{
public override void HandleRequest ( int request )
{
if ( request >= 0 && request < 10 )
{
Console . WriteLine ( "{0} hanterade begäran {1}" ,
denna . GetType (). Namn , begäran );
}
else if ( successor != null )
{
successor . HandleRequest ( förfrågan );
}
}
}
/// <summary>
/// Klassen 'ConcreteHandler2'
/// </summary>
klassen ConcreteHandler2 : Handler
{
public override void HandleRequest ( int request )
{
if ( request >= 10 && request < 20 )
{
Console . WriteLine ( "{0} hanterade begäran {1}" ,
denna . GetType (). Namn , begäran );
}
else if ( successor != null )
{
successor . HandleRequest ( förfrågan );
}
}
}
/// <summary>
/// 'ConcreteHandler3'-klassen
/// </summary>
-klassen ConcreteHandler3 : Handler
{
public override void HandleRequest ( int request )
{
if ( request >= 20 && request < 30 )
{
Console . WriteLine ( "{0} hanterade begäran {1}" ,
denna . GetType (). Namn , begäran );
}
else if ( successor != null )
{
successor . HandleRequest ( förfrågan );
}
}
}
}
Output
ConcreteHandler1 hanterade förfrågan 2
ConcreteHandler1 hanterade förfrågan 5
ConcreteHandler2 hanterade förfrågan 14
ConcreteHandler3 hanterade förfrågan 22
ConcreteHandler2 hanterade förfrågan 18
ConcreteHandler1 hanterade förfrågan 3
ConcreteHandler3 behandlade förfrågan 27
ConcreteHandler3 hanterade förfrågan 20
C++ exempel
Källtext i
C++
#include <iostream>
/**
* Hjälparklass som beskriver något brott
*/
klass CriminalAction {
vänklass Polis ; _ // Polisen har tillgång till materialet i utredningen
int komplexitet ; // Fallets komplexitet
const char * beskrivning ; // Kort beskrivning av brottet
offentliga :
CriminalAction ( int complexity , const char * description ) : komplexitet ( komplexitet ), beskrivning ( beskrivning ) {}
};
/**
* En abstrakt polis som kan utreda brott
*/
klass polis {
skyddad :
int reduktion ; // avdrag (förmågan att reda ut komplexa fall) för denna polis
Polisman * nästa ; // en skickligare polis som får ett ärende om det är för jobbigt för den nuvarande
virtuellt void undersökConcrete ( const char * description ) {} // faktisk undersökning
offentliga :
Polisman ( int avdrag ) : avdrag ( avdrag ), nästa ( nullptr ) {}
virtuell ~ Polis () {
ta bort nästa ;
}
/**
* Lägger till en mer erfaren polis i ansvarskedjan som kan ta över
* utredningen om den nuvarande misslyckas
*/
Polisman * setNext ( Polisman * polisman ) {
nästa = polisman ;
återvända nästa ;
}
/**
* Polismannen inleder en utredning eller, om ärendet är för komplicerat, lämnar han det vidare till en mer erfaren kollega
*/
void undersöka ( CriminalAction * criminalAction ) {
if ( deduktion < criminalAction -> komplexitet ) {
if ( nästa ) {
nästa -> undersöka ( criminalAction );
} annat {
std :: cout << "Detta fall ska inte avslöjas för någon." << std :: endl ;
}
} annat {
undersöka Concrete ( kriminellAction -> description );
}
}
};
klass MartinRiggs : offentlig polis {
skyddad :
void investigateConcrete ( const char * description ) {
std :: cout << "Utredning av ärendet \" " << beskrivning << " \" ledd av sergeant Martin Riggs" << std :: endl ;
}
offentliga :
MartinRiggs ( int avdrag ) : Polis ( avdrag ) {}
};
klass JohnMcClane : offentlig polis {
skyddad :
void investigateConcrete ( const char * description ) {
std :: cout << "Utredning \" " << beskrivning << " \" Detektiv John McClane" << std :: endl ;
}
offentliga :
JohnMcClane ( int avdrag ) : Polis ( avdrag ) {}
};
klass Vincent Hanna : offentlig polis {
skyddad :
void investigateConcrete ( const char * description ) {
std :: cout << "Utredning av ärendet \" " << beskrivning << " \" ledd av löjtnant Vincent Hanna" << std :: endl ;
}
offentliga :
VincentHanna ( int avdrag ) : Polis ( avdrag ) {}
};
int main () {
std :: cout << "OUTPUT:" << std :: endl ;
Polis * polis = ny MartinRiggs ( 3 ); // polis med minst undersökande skicklighet polis
-> setNext ( ny JohnMcClane ( 5 ))
-> setNext ( ny Vincent Hanna ( 8 )); // lägg till två erfarna poliskollegor till honom -> undersök ( ny CriminalAction ( 2 , "Droghandel från Vietnam" ));
polisman -> undersöka ( ny CriminalAction ( 7 , "Ett vågat bankrån i centrala Los Angeles" ));
polisman -> undersöka ( ny CriminalAction ( 5 , "Series of explosions in downtown New York" ));
returnera 0 ;
}
/**
* OUTPUT:
* Undersöker narkotikahandeln i Vietnam av sergeant Martin Riggs
* Undersöker djärvt bankrån i centrala Los Angeles av löjtnant Vincent Hanna
* Undersöker en serie bombdåd i centrala New York med detektiv John McClain som värd
*/
Python-exempel
Källkod i
Python
hanterare = []
def car_handler ( func ):
hanterare . lägga till ( func )
returnera func
klass Bil :
def __init__ ( själv ):
själv . namn = Inget
själv . km = 11100
själv . bränsle = 5
själv . olja = 5
@car_handler
def handle_fuel ( bil ):
om bil . bränsle < 10 :
print ( "tillsatt bränsle" )
bil . bränsle = 100
@car_handler
def handle_km ( bil ):
om bil . km > 10000 :
print ( "gjort ett biltest." )
bil . km = 0
@car_handler
def handle_oil ( bil ):
om bil . olja < 10 :
print ( "Tillsatt olja" )
bil . olja = 100
klass Garage :
def __init__ ( själv , hanterare = Inga ):
själv . hanterare = hanterare eller []
def add_handler ( själv , hanterare ):
själv . hanterare . lägga till ( hanterare )
def handle_car ( själv , bil ):
för hanterare i själv . hanterare :
hanterare ( bil )
om __name__ == '__main__' :
garage = Garage ( hanterare )
bil = Bil ( )
garage . handle_car ( bil )
Länkar
Anteckningar
- ↑ Ansvarskedja i Delphi