τα στοιχεία επικοινωνίας μου
Ταχυδρομείοmesophia@protonmail.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Μοτίβο αλυσίδας ευθύνης: Αποφύγετε τη σύζευξη του αποστολέα και του παραλήπτη του αιτήματος, δώστε την ευκαιρία σε πολλά αντικείμενα να λάβουν το αίτημα, συνδέστε αυτά τα αντικείμενα σε μια αλυσίδα και περάστε το αίτημα κατά μήκος αυτής της αλυσίδας μέχρι να υπάρξει ένα αντικείμενο για να το χειριστεί.Το μοντέλο της αλυσίδας ευθύνης είναι αμοτίβο συμπεριφοράς αντικειμένου。
Ο πυρήνας της δομής του προτύπου της αλυσίδας ευθύνης είναι η εισαγωγή του ααφηρημένο επεξεργαστή
Όπως φαίνεται από το σχήμα, το διάγραμμα δομής προτύπων αλυσίδας ευθύνης περιέχει τους ακόλουθους δύο ρόλους:
(1) Handler (αφηρημένος χειριστής): Ορίζει μια διεπαφή για την επεξεργασία αιτημάτων και γενικά σχεδιάζεται ως αφηρημένη κλάση. Επειδή διαφορετικοί χειριστές σκυροδέματος χειρίζονται διαφορετικά αιτήματα, ορίζονται σε αυτά αφηρημένες μέθοδοι χειρισμού αιτημάτων.Επειδή ο δευτερεύων κάθε επεξεργαστής εξακολουθεί να είναι ένας επεξεργαστής, ένα αντικείμενο του τύπου αφηρημένου επεξεργαστή (διάδοχος στο διάγραμμα δομής) ορίζεται στον αφηρημένο επεξεργαστή ως δευτερεύον του.Παραθέτω, αναφορά . Μέσω αυτής της αναφοράς, οι χειριστές μπορούν να συνδεθούν σε μια αλυσίδα.
(2) ConcreteHandler (concrete handler): Είναι μια υποκατηγορία αφηρημένου χειριστή και μπορεί να χειριστεί αιτήματα χρηστών.Η μέθοδος επεξεργασίας αφηρημένων αιτημάτων που ορίζεται στον επεξεργαστή αφηρημένων υλοποιείται στην κλάση του συγκεκριμένου επεξεργαστή και μπορεί να έχει πρόσβαση στο επόμενο αντικείμενο στην αλυσίδα για να επιτύχειΑίτημα προώθησηςΑποτέλεσμα.
Στο μοτίβο Chain of Responsibility, οι αναφορές κάθε αντικειμένου στους απογόνους του συνδέονται για να σχηματίσουν μια αλυσίδα. Τα αιτήματα διαβιβάζονται σε αυτήν την αλυσίδα μέχρι ποιο αντικείμενο στην αλυσίδα χειρίζεται τελικά το αίτημα. Αυτό επιτρέπει στο σύστημα να αναδιοργανώσει δυναμικά την αλυσίδα και να εκχωρήσει ευθύνες χωρίς να επηρεάσει τον πελάτη.
Ο πυρήνας του προτύπου της αλυσίδας ευθύνης βρίσκεται στο σχεδιασμό της κατηγορίας αφηρημένου χειριστή Ο τυπικός κώδικας της κατηγορίας αφηρημένου χειριστή είναι ο εξής:
abstract class Handler {
//维持对下家的引用
protected Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(String request);
}
Στον παραπάνω κώδικα, ο αφηρημένος επεξεργαστής ορίζει ένα αντικείμενο αναφοράς στον επόμενο επεξεργαστή για να προωθήσει το αίτημα στον επόμενο επεξεργαστή. Το accessor αυτού του αντικειμένου μπορεί να ρυθμιστεί σε προστατευμένο, το οποίο μπορεί να χρησιμοποιηθεί στις υποκατηγορίες του.
Οι χειριστές σκυροδέματος είναι υποκατηγορίες αφηρημένων χειριστών και έχουν δύο κύριες λειτουργίες:
Ο τυπικός κώδικας για μια συγκεκριμένη κατηγορία χειριστή είναι ο εξής:
class ConcreteHandler extends Handler {
public void handleRequest(String request) {
if (请求满足条件) {
//处理请求
}
else {
this.successor.handleRequest(request); //转发请求
}
}
}
Ένα συγκεκριμένο σύστημα έγκρισης παραγγελίας αγοράς είναι ιεραρχικό, δηλαδή εγκρίνεται από επόπτες σε διαφορετικά επίπεδα ανάλογα με το ποσό αγοράς.
Ο διευθυντής μπορεί να εγκρίνει εντολές αγοράς κάτω των 50.000 γιουάν, ο αντιπρόεδρος μπορεί να εγκρίνει εντολές αγοράς ύψους [5.100.000 γιουάν], ο πρόεδρος του διοικητικού συμβουλίου μπορεί να εγκρίνει εντολές αγοράς [10.500.000 γιουάν] και εντολές αγοράς 5000 γιουάν. και παραπάνω απαιτείται συνεδρίαση του διοικητικού συμβουλίου για συζήτηση και απόφαση.
Δεδομένου ότι οι εγκρίοντες κάθε θέσης έχουν υφισταμένους (εκτός από το διοικητικό συμβούλιο) και οι συμπεριφορές τους είναι κοινές, όλοι περιλαμβάνουν την προώθηση εγκρίσεων στους διαδόχους τους. Σχεδιάστε λοιπόν μια κλάση έγκρισης ως αφηρημένο επεξεργαστή:
//审批者类: 抽象处理者
abstract class Approver {
protected Approver successor; //定义后继对象
protected String name; //审批者姓名
public Approver(String name) {
this.name = name;
}
//设置后继者
public void setSuccessor(Approver successor) {
this.successor = successor;
}
public abstract void processRequest(PurchaseRequest request);
}
Στη συνέχεια, κάθε θέση, ως συγκεκριμένος επεξεργαστής, πρέπει να εφαρμόσει έναν αφηρημένο επεξεργαστή:
//主任: 具体处理者
class Director extends Approver{
public Director(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < 50000) {
System.out.println(
MessageFormat.format("主任 {0} 审批采购单:{1}, 金额:{2}元, 采购目的:{3}。",
this.name, request.getNumber(), request.getAmount(), request.getPurpose())
);
} else {
this.successor.processRequest(request); //转发请求
}
}
}
//副董事长:具体处理类
class VicePresident extends Approver{
public VicePresident(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < 100000) {
System.out.println(
MessageFormat.format("副董事长 {0} 审批采购单:{1}, 金额:{2}元, 采购目的:{3}。",
this.name, request.getNumber(), request.getAmount(), request.getPurpose())
);
} else {
this.successor.processRequest(request);
}
}
}
//董事长类:具体处理者
class President extends Approver{
public President(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < 500000) {
System.out.println(
MessageFormat.format("董事长 {0} 审批采购单:{1}, 金额:{2}元, 采购目的:{3}。",
this.name, request.getNumber(), request.getAmount(), request.getPurpose())
);
} else {
this.successor.processRequest(request);
}
}
}
//董事会类:具体处理者
class Congress extends Approver{
public Congress(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
System.out.println(
MessageFormat.format("召开董事会 审批采购单:{0}, 金额:{1}元, 采购目的:{2}。",
request.getNumber(), request.getAmount(), request.getPurpose())
);
}
}
Καθορίστε μια άλλη κατηγορία παραγγελίας αγοράς ως στόχο που πρέπει να εγκριθεί:
//采购单: 请求类
class PurchaseRequest {
private double amount; //采购金额
private int number; //采购单编号
private String purpose; //采购目的
public PurchaseRequest(double amount, int number, String purpose) {
this.amount = amount;
this.number = number;
this.purpose = purpose;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getPurpose() {
return purpose;
}
public void setPurpose(String purpose) {
this.purpose = purpose;
}
}
Γράψτε τον κωδικό δοκιμής πελάτη:
class Client {
public static void main(String[] args) {
Approver kangXi, yongZheng, qianLong, hanLinYuan;
kangXi = new Director("康熙");
yongZheng = new VicePresident("雍正");
qianLong = new VicePresident("乾隆");
hanLinYuan = new Congress("翰林院");
//创建职责链
kangXi.setSuccessor(yongZheng);
yongZheng.setSuccessor(qianLong);
qianLong.setSuccessor(hanLinYuan);
//创建采购单
PurchaseRequest pr1 = new PurchaseRequest(45000, 10001, "购买刀");
kangXi.processRequest(pr1);
PurchaseRequest pr2 = new PurchaseRequest(60000, 10002, "购买枪");
kangXi.processRequest(pr2);
PurchaseRequest pr3 = new PurchaseRequest(160000, 10003, "购买火炮");
kangXi.processRequest(pr3);
PurchaseRequest pr4 = new PurchaseRequest(800000, 10004, "购买军舰");
kangXi.processRequest(pr4);
}
}
Μεταγλώττιση και εκτέλεση του προγράμματος, η έξοδος είναι η εξής:
主任 康熙 审批采购单:10,001, 金额:45,000元, 采购目的:购买刀。
副董事长 雍正 审批采购单:10,002, 金额:60,000元, 采购目的:购买枪。
董事长 乾隆 审批采购单:10,003, 金额:160,000元, 采购目的:购买火炮。
召开董事会 审批采购单:10,004, 金额:800,000元, 采购目的:购买军舰。
Ας σχεδιάσουμε μια περίπτωση που είναι ελαφρώς διαφορετική από τα παραπάνω, η οποία μπορεί να διευρύνει την κατανόησή μας για το μοντέλο της αλυσίδας ευθύνης και τα σενάρια στα οποία μπορεί να εφαρμοστεί.
Το σχολείο θα αναθέσει ορισμένες εργασίες στην τάξη για επεξεργασία Αυτοί οι τύποι περιλαμβάνουν ένα, δύο, τρία, τέσσερα, κ.λπ. ένα, δύο, η επιτροπή εκμάθησης μπορεί να χειριστεί ένα από αυτά τα καθήκοντα. Όταν ο δάσκαλος της τάξης λάβει μια εργασία, θα την παραδώσει πρώτα στον αρχηγό της ομάδας για επεξεργασία, ο δάσκαλος της τάξης θα το χειριστεί μόνος του Στη σχολική επιτροπή για επεξεργασία, εάν η επόμενη τάξη δεν μπορεί να το χειριστεί, ο δάσκαλος της τάξης θα το χειριστεί ο ίδιος όταν η σχολική επιτροπή λάβει μια εργασία, θα τη χειριστεί μόνος του. Και όταν δεν μπορούν να το χειριστούν, θα δίνουν ανατροφοδότηση προς τα πάνω.
Η κλάση Handler έχει σχεδιαστεί παρακάτω ως αφηρημένος επεξεργαστής:
Δεδομένου ότι εσείς και οι υφιστάμενοί σας μπορεί να μην είστε απαραίτητα σε θέση να χειριστείτε ορισμένες εργασίες κλάσης και υπάρχει ανάδραση προς τα πάνω, η μέθοδος αιτήματος του επεξεργαστή πρέπει να έχει μια δυαδική τιμή επιστροφής για να πει στον ανώτερο αν μπορεί να χειριστεί την εργασία.
abstract class Handler {
protected Handler successor; //定义后继对象
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract boolean handleRequest(String taskName);
}
Παρακάτω, ο δάσκαλος της τάξης, ο αρχηγός της ομάδας και το μέλος της επιτροπής μελέτης σχεδιάζονται αντίστοιχα ως συγκεκριμένοι χειριστές.
Από προεπιλογή, ο δάσκαλος της τάξης θα δώσει πρώτα την εργασία στον αρχηγό της ομάδας και ο αρχηγός της ομάδας θα δώσει την εργασία στο μέλος της επιτροπής μελέτης από προεπιλογή , θα επιστρέψει ψευδής.
Εάν η ανατροφοδότηση που λαμβάνει ο αρχηγός της ομάδας είναι ψευδής, θα τα χειριστεί μόνος του.
Εάν η ανατροφοδότηση που λαμβάνει ο διευθυντής είναι ψευδής, θα τα χειριστεί μόνος του. Μπορεί να χειριστεί μόνο εργασίες ενός, δύο και τριών τύπων.
//班主任
class HeadTeacher extends Handler{
@Override
public boolean handleRequest(String taskName) {
boolean handled = successor.handleRequest(taskName);
if (handled) {
return true;
}
if (taskName.equals("one") || taskName.equals("two") || taskName.equals("three")) {
System.out.println("班主任处理了该事务");
return true;
}
return false;
}
}
//班长
class Monitor extends Handler{
@Override
public boolean handleRequest(String taskName) {
boolean handled = successor.handleRequest(taskName);
if (handled) {
return true;
}
if (taskName.equals("one") || taskName.equals("two")) {
System.out.println("班长处理了该事务");
return true;
}
return false;
}
}
//学习委员
class StudyCommissary extends Handler{
@Override
public boolean handleRequest(String taskName) {
boolean handled;
if (successor == null) { //注意学习委员可能没有下家,所以这里判一下是否为空
handled = false;
} else {
handled = successor.handleRequest(taskName);
}
if (handled) {
return true;
}
if (taskName.equals("one")) {
System.out.println("学习委员处理了该事务");
return true;
}
return false;
}
}
Γράψτε τον κωδικό δοκιμής πελάτη:
Δημιουργήστε υποσπίτια για κάθε θέση, αλλά σημειώστε ότι δεν υπάρχει υποσπίτι για μέλη της επιτροπής μελέτης.
Επίσης, εάν υπάρχει μια εργασία που ο διευθυντής δεν μπορεί να χειριστεί, εκτυπώστε μια γραμμή καταγραφής για να την εξηγήσετε.
public class SchoolClient {
public static void main(String[] args) {
Handler headTeacher, monitor, studyCommissary;
headTeacher = new HeadTeacher();
monitor = new Monitor();
studyCommissary = new StudyCommissary();
headTeacher.setSuccessor(monitor);
monitor.setSuccessor(studyCommissary);
studyCommissary.setSuccessor(null); //没有下一职责人
startRequest(headTeacher, "one");
startRequest(headTeacher, "two");
startRequest(headTeacher, "three");
startRequest(headTeacher, "four");
}
private static void startRequest(Handler headTeacher, String taskName) {
if (! headTeacher.handleRequest(taskName)) {
System.out.println("该班级处理不了此类任务!");
}
}
}
Μεταγλώττιση και εκτέλεση του προγράμματος, η έξοδος είναι η εξής:
学习委员处理了该事务
班长处理了该事务
班主任处理了该事务
该班级处理不了此类任务!
Το μοντέλο Chain of Responsibility μπορεί να εξεταστεί στις ακόλουθες περιπτώσεις:
Βιβλία αναφοράς:
"The Art of Design Patterns" - Liu Wei