Mẫu Hành Vi - Mẫu Chuỗi Trách Nhiệm: Tình Huống Sử Dụng, Triển Khai, Ưu Nhược Điểm

Giới thiệu

Mẫu Chuỗi Trách Nhiệm (Chain of Responsibility Pattern) là một mẫu hành vi cho phép phân tán yêu cầu thông qua một chuỗi các đối tượng xử lý. Mục tiêu chính là giảm sự phụ thuộc trực tiếp giữa người gửi yêu cầu và người nhận, đồng thời tạo tính linh hoạt trong việc mở rộng hoặc thay đổi luồng xử lý.

Các thành phần chính

  • Handler (Bộ xử lý): Giao diện hoặc lớp trừu tượng xác định phương thức xử lý yêu cầu và tham chiếu đến bộ xử lý tiếp theo.
  • ConcreteHandler (Bộ xử lý cụ thể): Triển khai logic xử lý riêng biệt. Nếu không thể xử lý, yêu cầu sẽ được chuyển cho bộ xử lý kế tiếp.
  • Client (Người gọi): Khởi tạo chuỗi xử lý bằng cách gửi yêu cầu đến bộ xử lý đầu tiên.

Tình huống áp dụng

  1. Nhiều đối tượng có thể xử lý yêu cầu: Người gửi không cần biết chính xác đối tượng nào sẽ xử lý.
  2. Thay đổi động luồng xử lý: Có thể thêm/bớt hoặc sắp xếp lại thứ tự các bộ xử lý.
  3. Thứ tự xử lý quan trọng: Đảm bảo yêu cầu được xử lý theo quy trình định trước.

Ví dụ triển khai

Xét hệ thống phê duyệt chi tiêu trong doanh nghiệp, nơi mỗi cấp bậc có giới hạn xử lý khác nhau.

Giao diện Bộ xử lý

public interface XửLýYêuCầu {
    void xửLý(YêuCầu yc);
    void setKếTiếp(XửLýYêuCầu bộXửLý);
}

Lớp trừu tượng Bộ xử lý

public abstract class BộXửLý implements XửLýYêuCầu {
    protected XửLýYêuCầu bộXửLýKếTiếp;

    @Override
    public void setKếTiếp(XửLýYêuCầu bộXửLý) {
        this.bộXửLýKếTiếp = bộXửLý;
    }

    @Override
    public abstract void xửLý(YêuCầu yc);
}

Bộ xử lý cấp độ 1

public class GiámĐốcChiNhánh extends BộXửLý {
    @Override
    public void xửLý(YêuCầu yc) {
        if (yc.getSốTiền() <= 10_000_000) {
            System.out.println("Giám đốc chi nhánh phê duyệt " + yc.getSốTiền());
        } else if (bộXửLýKếTiếp != null) {
            bộXửLýKếTiếp.xửLý(yc);
        }
    }
}

Bộ xử lý cấp độ 2

public class GiámĐốcToànQuốc extends BộXửLý {
    @Override
    public void xửLý(YêuCầu yc) {
        if (yc.getSốTiền() > 10_000_000 && yc.getSốTiền() <= 100_000_000) {
            System.out.println("Giám đốc toàn quốc phê duyệt " + yc.getSốTiền());
        } else if (bộXửLýKếTiếp != null) {
            bộXửLýKếTiếp.xửLý(yc);
        }
    }
}

Lớp Người gọi

public class ỨngDụng {
    public static void main(String[] args) {
        XửLýYêuCầu cấp1 = new GiámĐốcChiNhánh();
        XửLýYêuCầu cấp2 = new GiámĐốcToànQuốc();
        
        cấp1.setKếTiếp(cấp2); // Xây dựng chuỗi
        
        YêuCầu yêuCầu = new YêuCầu(50_000_000);
        cấp1.xửLý(yêuCầu); // Bắt đầu xử lý
    }
}

Ưu điểm

  • Giảm kết nối trực tiếp: Người gửi và người nhận không cần biết về nhau.
  • Dễ mở rộng: Thêm/bớt bộ xử lý mà không ảnh hưởng đến luồng xử lý.

Nhược điểm

  • Yêu cầu có thể bị bỏ qua: Nếu không có bộ xử lý nào phù hợp.
  • Tốn hiệu năng: Do yêu cầu phải đi qua nhiều bước kiểm tra.

Thẻ: design-patterns behavioral-patterns chain-of-responsibility

Đăng vào ngày 3 tháng 8 lúc 08:33