Az objektumorientált tervezésben a felelősséglánc egy tervezési minta, amely parancsobjektumokból és feldolgozó objektumokból áll. Minden egyes feldolgozó objektum tartalmazza azt a logikát, amellyel a parancsobjektum definiálható és kezelhető, valamint olyan folyamatokat, amiket kidolgozásra továbbadhat a lánc egy következő folyamatának. Olyan mechanizmus is létezik, amivel lehetőségünk adódik arra, hogy a felelősséglánc végén egy újabb feldolgozó objektumot adjunk hozzá.
A standard felelősséglánc egyik variációja úgy viselkedik, mint egy diszpécserközpont, mert képes parancsokat küldeni különböző irányokba, amivel át tudja alakítani a felelősségláncot. Bizonyos esetekben előfordulhat rekurzió. Ez akkor történik, amikor az éppen aktuálisan futó objektum meghív egy magasabban futó műveletet egy paranccsal, aminek az a célja, hogy a futó objektum kisebb részekre vágásával megpróbálja megoldani a problémát. Ebben az esetben a rekurzió vagy addig folytatódik, amíg a parancs futását le nem állítjuk, vagy addig, amíg az összes ágat be nem futja. Az XML fordító működik rekurzív módon.
Ez a tervezési minta hozzájárult a laza csatoltság ötletéhez, ami az egyik legjobb programozási gyakorlatnak tekinthető.
Példa
Java példa Az alábbi példa bemutatja a tervezési mintát Java nyelven. Ebben a példában különböző szerepeket mutatunk be, ezek mindegyike tartalmaz egy fix fizetési limitet, valamint öröklődést. Minden alkalommal, amikor a felhasználó meghívja a fizetési kérést, és a kérésben szereplő összeg meghaladja a fixre állított fizetési limitet, a kérést átadja az osztály a gyermekének.
A PurchasePower egy abstract osztály, egy processRequest nevű absztrakt metódussal. abstract class PurchasePower { protected static final double BASE = 500; protected PurchasePower successor;
public void setSuccessor(PurchasePower successor) { this.successor = successor;
abstract public void processRequest(PurchaseRequest request); } Az abstract osztály felett négy megvalósítás van: Manager, Director, Vice President, President. class ManagerPPower extends PurchasePower { private final double ALLOWABLE = 10 * BASE;
public void processRequest(PurchaseRequest request) { if (request.getAmount() < ALLOWABLE) { System.out.println("Manager will approve $" + request.getAmount()); } else if (successor != null) { successor.processRequest(request);
class DirectorPPower extends PurchasePower { private final double ALLOWABLE = 20 * BASE;
public void processRequest(PurchaseRequest request) { if (request.getAmount() < ALLOWABLE) { System.out.println("Director will approve $" + request.getAmount()); } else if (successor != null) { successor.processRequest(request);
class VicePresidentPPower extends PurchasePower { private final double ALLOWABLE = 40 * BASE;
public void processRequest(PurchaseRequest request) { if (request.getAmount() < ALLOWABLE) { System.out.println("Vice President will approve $" + request.getAmount()); } else if (successor != null) { successor.processRequest(request);
class PresidentPPower extends PurchasePower { private final double ALLOWABLE = 60 * BASE;
public void processRequest(PurchaseRequest request) { if (request.getAmount() < ALLOWABLE) { System.out.println("President will approve $" + request.getAmount()); } else { System.out.println( "Your request for $" + request.getAmount() + " needs a board meeting!");
}A következő kód definiálja a PurchaseRequest osztályt és beállítja a kért adatokat. class PurchaseRequest { private double amount; private String purpose;
public PurchaseRequest(double amount, String purpose) { this.amount = amount; this.purpose = purpose;
public double getAmount() { return amount;
public void setAmount(double amt) { amount = amt;
public String getPurpose() { return purpose;
public void setPurpose(String reason) { purpose = reason;
}A következő példában az örökös osztályok beállítják a korábban definiált megvalósításokat, ebben a sorrendben: Manager -> Director -> Vice President -> President. class CheckAuthority { public static void main(String[] args) { ManagerPPower manager = new ManagerPPower(); DirectorPPower director = new DirectorPPower(); VicePresidentPPower vp = new VicePresidentPPower(); PresidentPPower president = new PresidentPPower(); manager.setSuccessor(director); director.setSuccessor(vp); vp.setSuccessor(president);
// Press Ctrl+C to end. try { while (true) { System.out.println("Enter the amount to check who should approve your expenditure."); System.out.print(">"); double d = Double.parseDouble(new BufferedReader(new InputStreamReader(System.in)).readLine()); manager.processRequest(new PurchaseRequest(d, "General"));
} catch(Exception e) { System.exit(1);
Megvalósítások
A Cocoa és a Cocoa Touch keretrendszer A Cocoa és Cocoa Touch keretrendszert az OS X és iOS operációs rendszerek használják. A két keretrendszer gyakran használja a felelősséglánc tervezési mintát az események kezelésére. Az objektumok meghívnak egy válaszadó objektumot, ami öröklődik az NSResponder (OS X)/UIResponder (iOS) osztályokban. Az összes nézet objektumban (NSView/UIView), nézetet irányító objektumban (NSViewController/UIViewController), ablak objektumokban (NSWindow/UIWindow), valamint az applikációs objektumban (NSApplication/UIApplication) van válaszadó objektum
Tipikusan, amikor a nézet kap egy eseményt, amit nem tud kezelni, kiszervezi azt a nézet irányító, vagy az ablak objektumokba. Ha ezek az objektumok sem tudják kezelni az eseményt, akkor ők is kiszervezik az applikációs objektum felé, ami a láncban az utolsó objektum.
Például: OS X-en, amikor megmozdítasz egy ablakot az egérrel, akkor azt normál estben bárhová le lehet tenni. Kivételt képez az a helyzet, amikor egy másik esemény útban van (pl. csúszkairányító), ha nincs nézet (vagy szupernézet), hogy azt lekezelje, akkor az operációs rendszer elküldi az eseményt a felelősségláncba, átadva így a felelősséget annak. iOS-en éppen a mozgatott esemény az, amelyik vezeti a hierarchiát a nézet alatti osztály helyett. Övé a prioritás, és ha ez problémát okoz, akkor a válaszadó lánc felfüggeszti az összes nézeteseményt, és lekezelni a problémás részt.
Kapcsolódó szócikkek Egyszeres felelősség elve
További információk https://web.archive.org/web/20180227070352/http://www.blackwasp.co.uk/ChainOfResponsibility.aspx
Fordítás
Kategória:Programtervezési minták Kategória:Java-kódpéldák